관리 메뉴

기억을 위한 기록들

[CPP-effective] 1-2 낌새만 보이면 const를 넣자. 본문

C & CPP/Effective C++

[CPP-effective] 1-2 낌새만 보이면 const를 넣자.

에드윈H 2021. 2. 23. 18:06

const는 상수(constant)로 변하지 않는 값이다.

 

https://terms.naver.com/entry.nhn?docId=1109846&cid=40942&categoryId=32206

 

 

 

-const가 *의 왼쪽에 있으면 포인터가 가리키는 대상이 상수.

-const가 *의 오른쪽에 있으면 포인터자체가 대상이 상수.

-const가 둘다 있으면 포인터자체와 포인터가 가리키는 대상 둘다 상수이다.

	int text = 5;
	int text2 = 7;

	const int* p1 = &text; //비상수 포인터 - 상수 데이터
	//*p1 = 12;   // 에러 -> 데이터 변경 불가
	p1 = &text2;  // 성공 -> 주소변경


	int* const p2 = &text; //상수 포인터 - 비상수 데이터 	
	*p2 = 8;        //성공 ->데이터 변경
	//p2 = &text2; // 에러 -> 주소변경불가
	

	const int* const p3 = &text; //상수 포인터 - 상수 데이터
	//*p3 = 8;      //에러 ->데이터변경불가
	//p2 = &text2; // 에러 -> 주소변경불가

 

그런데 const가 * 왼쪽에 있는 경우가 2가지 인데 의미적인 차이는 없다.

void f1(const Widget* pw);

void f1(Widget const* pw);

//매개변수 타입은 모두 같다.

 

 

상수 멤버 함수

- 멤버 함수에 붙는 const 키워드의 역할은 "해당 멤버 함수가 상수 객체에 대해 호출될 함수이다" 라는걸 알려준다.

중요한 이유는 2가지로,

1. 클래스의 인터페이스를 이해하기 좋게 하기 위해서.

2. 이 키워드를 통해 상수 객체를 사용할 수 있게 하자는것인데 코드의 효율을 위함.

 

C++ 프로그램의 실행 성능을 높이는 핵심 기법 중 하나가 객체 전달을 상수 객체에 대한 참조자로 진행하 는것이다.

이 기법이 제대로 사용하려면 상수멤버함수가 준비되어있어야한다는 점이 포인트이다.

 

const 키워드의 유무차이에 대한 함수 오버로딩 가능

class Player{
	//...
public:
    int GetHP() const; //상수 객체에대한 GetHP
    int GetHP();   //비 상수객체에 대한 GetHP
    
    ///..
};

int Player::GetHP() const
{
	return 0;
}

int Player::GetHP()
{
	return 100;
}

 

Player* A=new Player(); 
A->GetHP(); //비 상수 멤버함수 호출 -> 100 출력

const Player* B=new Player();
B->GetHP(); //상수 멤버함수 호출 -> 0 출력

 

void Test(const Player& ref) //상수 객체 전달
{
	std::cout << ref.GetHP() << std::endl; //상수 멤버 함수 0 출력
}


void Test(Player& ref) //비상수 객체 전달
{
	std::cout << ref.GetHP() << std::endl; //상수 멤버 함수 100 출력
}

 

 

 

정리

* const를 붙여 선언하면 컴파일러가 에러를 잡는데 도움을 준다.  대부분 유효범위안에 붙일수 있다.(함수 매개변수, 함수 반환 타입, 멤버함수 등)

 

* 컴파일러쪽에서 보면 비트수준 상수성을 지켜야하지만, 우리는 논리적인 상수성을 사용해서 프로그래밍 해야함.

 

* 상수멤버함수, 비상수멤버 함수가 기능적으로 똑같게 구현되어 있을 경우에, 코드 중복을 피하는게 좋은데, 이때 비상수 버전이 상수버전을 호출 하도록하게 하자.