개발자 면접 공부/C-C++

Constexpr VS Const

chogyujin 2023. 5. 9. 21:17
728x90

오늘은 ConstexprConst 의 차이점을 공부하도록 하겠습니다.


1. 개요

const 에 대해서는 프로그래밍 언어를 공부해본 사람들은 다 알고있는 사실인 상수 변수를 선언할때 쓰는 선언문입니다.
하지만 C++을 공부하면서 constexpr에 대해 알게되었고 매우 흥미로운 선언문이라는것도 알게되었습니다.
그래서 오늘은 const constexpr 에 대해 알아보도록 하겠습니다.

 


2. Const (상수)

const 는 일반적으로 모든 프로그래밍 언어??에서 상수역활을 합니다.
한번 초기화된 상수 변수는 다신 변수의 저장된 값을 변경할수가 없습니다.
또한, const는 선언과 동시의 초기화 작업을 이루어져야하는 값 입니다.
ex)

const int a = 5; // 성공적인 초기화
const int b; // 에러 const int type 입니다 초기화가 필요합니다.

이렇게 말이지요

또한 한번 지정된 즉 한번 초기화된 const type은 값에 변경이 불가합니다.

ex)

const int a = 5; // 성공적인 초기화
a = 6; // 에러 const int type 입니다.

이렇게 값을 변경할려면 에러를 뿝게 됩니다.

 

하지만 const 상수는 이런것이 가능합니다.

int a;
cin >> a;
const int b = a;

a라는 값을 아직 실행시간 전에 모르지만 실행후에 const int 안에 초기화가 가능합니다.

 

또한 함수 내부에도 사용이 가능합니다.

int Sum(const int a, const int b)
{
	a = 6; // 에러 const int type 입니다.
	b = 6; // 에러 const int type 입니다.
	return a + b;
}

int main()
{
	Sum(1, 2);
	return 0;
}

함수 매개변수로 const int 로 선언하여 인자를 받아줄수도 있습니다.

하지만 함수 내부에서 const 로 인자를 받아왔기 때문에 변경은 불가능합니다.

 

그렇다면 constexpr은 어떻게 다를가요?


3. Constexpr (상수)

constexpr은 const와 다르게 더욱 빡빡하게 초기화를 진행합니다.

앞서 const는 컴파일 시간에 값을 모르는 변수에 대해 실행시간에 유동적으로 초기화를 진행할수 있다고 설명하였습니다.

하지만 constexpr은 const와 다르게 실행시간에 유동적으로 받지않고 오직 컴파일 시간에만 초기화를 진행할수있습니다.

 

ex)

constexpr int a = 5; // 가능
int c;
cin >> c;
constexpr int x = c; // 에러 constexpr 형태입니다.

이렇게 에러가 나옵니다. 하지만 빨간줄로 나오지않고 빌드중에 에러를 뿝게 됩니다.

 

그렇다면 함수에 대해서는 어떻게 될가여???

int Sum(constexpr int a, constexpr int b)
{
	return a + b;
}

int main()
{
	int a = Sum(1, 2);

	return 0;
}

함수의 파라미터가 constexpr int type이라 안된다고 에러를 뿝게됩니다.

함수 또한 저 a랑 b가 컴파일중에 초기화를 하는것이 아닌 실행시간중에 아규먼트가 변할수있기 때문에 받질 못하기 때문입니다.

그렇다면 constexpr 을 인자값으로 넘겨주면 어떤 현상이 벌어질가요?

 

int Sum(constexpr int a, constexpr int b)
{
	return a + b;
}

int main()
{
	constexpr int a = 5;
	constexpr int b = 6;
	int c = Sum(a, b);

	return 0;
}

똑같은 현상이 발생합니다.

이로서 const와 constexpr의 차이점을 확실히 알았습니다.

 


4. 요약

Const Constexpr
실행시간의 초기화가 가능
ex) const int a = c;
실행시간의 초기화가 불가능
ex) constexpr int a = c // 에러 대상이 constexpr int 입니다.

 


5. 번외) const_cast

저번 포스팅에서 4가지의 cast중 const_cast를 공부한적이 있습니다.

과연 const_cast는 진짜로 const를 없애준것일가여?

int main()
{
	const int a = 6;
	int c = const_cast<int&>(a);
	c = 7;
	a = 1; // 에러 대상이 const int type입니다.
	return 0;
}

c에 const_cast를 통해 a에 상수를 없앴습니다.

하지만 저것은 함정일뿐 상수를 없앤 값만 c에 넣어주는것이고 a라는 값은 아직 작동을 하고있으며 a라는 값은 아직 스택 메모리에 저장이 되있을 뿐입니다.

그러므로 c의 값을 변경해도 a의 값은 변경되지않고 6이라는 상수 값만 가지고 있습니다.

 

하지만 주의할점은 저 상수 a가 포인터라면?

int main()
{
	const int* a = new int(5);
	int* c = const_cast<int*>(a);
	*c = 7;
	return 0;
}

*c 의 값을 7로 변경하자마자 *a의 값이 변경되는 것을 볼수가 있습니다.

아마 저의 추측이지만 const_cast를 통해 a의 값을 전달받는것이 아닌 주소값을 전달받았기때문에
같은 주소를 공유하는 a와 c는 c의 값의 변화에 따라 a의 값이 변화하기 떄문입니다.

이래서 const_cast를 잘못사용하면 큰일이 난다는것 같습니다.