const는 constant의 약자로 사전적 의미로 '상수'를 말합니다. C++에서도 const는 그 대상을 변경하지 못하는 '상수'라는 의미로 사용합니다.
const int num = 1;
int const num = 1;
num = 2; // Compile Error
위 두 선언 방식 모두 의미가 같습니다. 보통 const가 맨 앞에 오는 첫 번째 형식을 많이 사용합니다. 위와 같이 선언하면 num은 변할 수 없는 상수가 되는 것입니다. 또한 함수의 반환형이나 매개변수가 const 변수형일 때도 동일한 의미입니다.
const 변수는 반드시 선언 시 초기화를 해야 합니다. 초기화가 되지 않으면 컴파일 에러가 발생합니다. 그래서 class의 멤버 변수를 const로 선언할 때는 반드시 초기화 리스트를 사용해야 합니다.
class Foo
{
const int num; // 메모리 할당이 아님
Foo(void)
: num(1) // const int num = 1;
{
}
};
class Bar
{
const int num;
Bar(void)
{
num = 1; // Compile Error
// const int num;
// num = 1;
}
};
Foo의 num은 생성자에서 초기화 리스트로 1로 초기화 하고 있습니다. 이는 const int num = 1;과 동일한 의미입니다.
하지만 Bar의 num은 생성자에서 초기화 리스트를 사용하지 않고 함수 내부에서 초기화를 시도하고 있습니다. 이것은 초기화가 아니라 const int num;으로 const 변수를 선언한 후에 num = 1;을 시도하는 것이죠. 따라서 const 변수를 1로 재할당한다는 의미이므로 컴파일 에러가 발생합니다.
포인터와 const를 함께 사용하는 두 가지 방법이 있습니다.
첫 번째, const 위치가 맨 앞에 있으면서 포인터 변수가 가리키는 값을 상수화 시키는 경우.
int num = 1;
const int* ptr = # // *ptr을 상수화
*ptr = 2; // Compile Error
num = 2; // Pass
*ptr = 2; ptr이 const 변수이기 때문에 컴파일 에러가 발생 하지만 num = 2;는 num이 non-const 변수이기 때문에 정상입니다. 즉, 포인터 변수가 가리키는 num 자체가 상수화가 되는 것이 아닙니다. 값에 접근하는 ptr을 이용해 재할당 하는 것이 불가능합니다.
두 번째, const 위치가 type과 변수 이름 사이에 있으면서 포인터 변수 자체를 상수화 시키는 경우입니다.
int num1 = 1;
int num2 = 2;
int* const ptr = &num1; // ptr을 상수화
ptr = &num2; // Compile Error
포인터 변수란 대상의 주소 값을 저장하는 변수입니다. 즉, 위의 ptr은 자기 자신을 상수화 시키는 것이기 때문에 num2의 주소값으로 변경하려고 하면 컴파일 에러가 발생합니다.
int GetString(void) const; // Compile Error
class Foo
{
int num = 1;
int GetNum(void) const
{
int a = 1;
a++; // 지역 변수는 가능
num++; // Compile Error
return num;
}
};
const 멤버 함수는 이름 그대로 class의 멤버 함수만 const로 상수화를 시킬 수 있고 비-멤버 함수는 const 함수로 선언이 불가능합니다.
const의 위치는 함수 선언문 맨 뒤이고 이 의미는 해당 멤버 함수 내에서는 모든 멤버 변수를 상수화 시킨다는 의미입니다. 따라서 위와 같이 멤버 변수인 num은 변경할 수 없고 지역 변수인 a는 변경할 수 있는 것이죠.