[C++] C++11 constexpr
상수는 어떤 특징을 가지는가?
컴파일타임에 약속되고, 절대 변하지 않는다는 보장이 있어야 한다.
이러한 점을 컴파일러에게 알려주는 키워드가 바로 constexpr이다.
기존 const가 있는데 왜 constexpr이 따로 생겼나요?
아래의 예시를 보도록하자.
1. const
#include <iostream>
int main()
{
//const std::size_t Size = 10;
//int Array[Size];
//가능.
//초기화 이후 바뀌지 않는다.
//그렇다면 만약 ?
const std::size_t Size = 10;
size_t* Casted = const_cast<size_t*>(&Size);
*Casted = 50;
int Array[Size];
std::cout << sizeof(Array) / sizeof(int) << std::endl;
//10? 50?
//답은 10이다.
//why??? 제가 분명히 바꿨는데요 ...
}
왜 50이 아닌가?
물론 10이 나와야 하는 것은 맞다.
그래야 상수의 의도가 맞으니.
중요한 건 왜 그런가이다.
디스 어셈블리를 보도록 하자.
분명히 컴파일러는 시키는대로 바꾸기는 했다.
단지 기계어 코드 생성시 초기화 시점의 상수를 그대로 넣는다.
메모리에 액세스 하지 않는다.
프로그램 코드에 아예 용접이 된다.
물론 리터럴 문자열인 경우에는 이야기가 조금 달라지지만,
상수는 충분히 작다.
프로그램 코드에 그대로 입력시키면 된다.
#include <iostream>
int main()
{
const std::size_t Size = 10;
size_t* Casted = (size_t*)(&Size);
*Casted = 50;
std::cout << *Casted << std::endl;
//50 이 출력된다.
//메모리에 엑세스 한다.
std::cout << Size << std::endl;
//메모리에 엑세스 하지 않는다.
}
그러면 만약 다음과 같은 경우는?
#include <iostream>
const int Sum(int A, int B)
{
return A + B;
}
int main()
{
int Array[Sum(10, 10)];
//이건 안된다.
//컴파일러 입장에서는 무슨 값이 나올지를 모르기 때문이다.
}
Sum 함수의 Argument인 A와 B에는 뭐가 들어갈지 모른다는 거다.
아니 ? 나는 분명히 하드코딩된 10,10을 넣었다.
그러면 컴파일러 입장에서는 10,10을 계산해서 그냥 20으로 아까처럼 프로그램 코드에 용접시키면 될 것 아닌가?
허나 컴파일러는 반환형 const int를 그런의미로 해석 하지를 않는다.
이래서 나온것이 constexpr 반환형 함수 이다.
함수의 인자를 상수로 받은 결과에 대해서는 컴파일타임에 계산이 가능하니
그것을 프로그램 코드에 용접하도록 하는 것이다.
이제 constexpr를 반환형으로 사용해보자.
2. constexpr
#include <iostream>
constexpr int Sum(int A, int B)
{
return A + B;
}
int main()
{
//int Var1 = 10;
//int Array[Sum(Var1, 10)];
//No.
int Array[Sum(10, 10)];
//Okay.
//Sum(10,10) 은 컴파일 타임에 상수화 되었다.
}
마찬가지로 위의 예시는 당연히 안된다.
언뜻 보면 Var1이 10이고 바뀔리가 없잖아?
컴파일러는 바보인가? 이정도도 예측을 못하나?
라고 생각할 수도 있지만, 배열의 크기를 알아야 스택을 얼마나 확보를 할지를 정할 수 있다.
그럼 계산하고 스택 확보를 하면 되잖아? 근데 그게 안된다.
연산은 스택이 있어야 가능하다.
스택을 확보하려면 연산을 해야하고, 스택이 없으면 연산이 안되고.
딜레마다.
그래서 안되는 거다.
아래의 예시는 가능하다.
constexpr 를 사용해서 Sum(10,10) 을 미리 계산 했으므로 상수화 시켜
정적 배열의 크기로 전달 가능하다.
'C++' 카테고리의 다른 글
[C++] new[] , delete[] 오버로딩시 주의 사항. (0) | 2022.03.28 |
---|---|
[C++] const lvalue reference, rvalue reference (2) | 2022.03.23 |
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr (0) | 2022.03.19 |
[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const (0) | 2022.03.17 |
[C++] C++ 11 Argument로 전달된 정적 배열의 크기 (0) | 2022.03.05 |
댓글
이 글 공유하기
다른 글
-
[C++] new[] , delete[] 오버로딩시 주의 사항.
[C++] new[] , delete[] 오버로딩시 주의 사항.
2022.03.28 -
[C++] const lvalue reference, rvalue reference
[C++] const lvalue reference, rvalue reference
2022.03.23 -
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
[C++] 스마트 포인터 unique_ptr, shared_ptr, weak_ptr
2022.03.19 -
[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const
[C++] Type Casting 연산자 정리 static, dynamic,reinterpret, const
2022.03.17