1. constexpr과 상수표현식
constexpr란?
- 어떤식이 상수식 이라고 명시해주는 키워드 이다.
- 컴파일중 값을 평가하는 기능을 가지고 있다.
- 기본적으로 해당 변수가 상수인지 아닌지에 대해서 검사한다.
상수 예시)
const int max_files = 20; // max_files는 상수표현식이다.
const int limit = max_files + 1; // limit는 상수표현식이다.
int staff_size = 27; // 상수표현식이 아님.
const int sz = get_size(); // 상수표현식이 아님.
기본적으로 다들 알다시피, const 키워드가 앞에 들어간 객체들이 상수라고 알겠지만,
여기서 말하는 상수는 숫자(1,2,3,4...등) 또는 숫자가 초기값으로 들어있는 변수를 뜻한다.
그렇기 때문에 여기서 맨 마지막 sz변수 또한 상수표현식이 맞지 않냐 할 수 있지만,
sz는 일반적인 숫자값이 들어간 변수나 정수(상수)가 아닌 get_size()가 대입되어
해당 코드를 실행할때 까지 초기값을 알지 못하기 때문에 상수표현식이아니다.
때문에 사실 이해하기 쉽게 설명하자면 상수표현식 보단 정수상수식 이라는 표현이
조금 더 이해하기 쉬울 것이다.
그렇다면 이제 constexpr를 쓰는 방법에 대해서 알아보겠다.
2. constexpr 사용법
- constexpr는 변수 타입 앞부분에 선언을 하여 해당 변수가 상수표현식인지
아닌지를 컴파일러에서 확인이 가능하다. - constexpr 로 객체를 선언한다면 해당 객체는 컴파일 타임 상수로 정의된다.
constexpr int mf = 20; // 상수표현식(20)
constexpr int limit = mf + 1; // 상수표현식(mf + 1)
constexpr int sz = size(); //size가 constexpr로 선언된 함수 일때만 상수표현식이다.
size()같은 이런 함수는 constexpr 변수 초기값에 사용 가능할 만큼
함수자체가 간단한 함수여야 상수 표현식으로 인정가능하다.
3. constexpr의 여러 특징
constexpr는 위에 설명한 내용을 제외하고도 여러가지 특징이 있다.
1. 포인터 참조자 모두 constexpr로 정의가 가능하다.
- 단, 사용하는 객체는 엄격하게 제한된다.
- constexpr 포인터는 상수 nullptr이나, 0으로 초기화가 가능하다.
- 또한 고정주소에 위치한 객체를 결합 할 수 도 있다.
2. constexpr은 항상 const이지만, const는 constexpr가 아니다.
int num1;
const int num2 = num2;
위에 해당 코드 처럼 const의 경우 일단 num1의 값이 초기화가 안되어서
정확히 무슨 값인지는 몰라도 const 변수인 mum2에 num1의 값을 넣어서
num2의 값이 바뀌지 않게 만들수는 있지만,
constexpr int num3 = num1 //error! num1이 초기화가 안되어 정수인지 아닌지 모름.
위에서 설명했듯 constexpr의 경우 무조건 해당 변수에 대입하는 값이 정수.
즉, 제대로된 상수값이 아닌 경우 컴파일시에 값이 뭔지 모르기 때문에 에러가 난다.
3. constexpr 포인터로 함수 지역 변수를 가리킬수 없다.
- 함수 안에서 정의한 지역 변수는 보통 고정주소에 저장하지 않아서
constexpr 포인터로 이런 함수 지역변수를 가리킬 수 없다.
**즉, constexpr 포인터는 가리키는 객체의 주소가 고정이여야 사용이 가능하다.**
constexpr로 불가능한 것들
- 기본적으로 리터럴(literal)타입이 아닌 변수의 정의는 불가능하다.
- 리터럴 타입이란? : 컴파일러가 컴파일 타임에 정의할 수 있는 타입.
리터럴 타입인 변수들.
- void , int, char, bool, long, float, double등등,
- 리터럴 타입의 배열
- 레퍼런스 타입
- 디폴트 소멸자를 가지면서 람다함수,
Arggregate 타입(사용자 정의 생성자, 소멸자가 없으며 모든 멤버가 public) - pair 같은 애들. - constexpr 생성자를 가지면서 복사 및 이동 생성자가 없는 것들.
위에 것들을 리터럴 타입이라고 부름.
(참고로 C++ 14 부터 constexpr 생성자를 지원하여 리터럴 타입을 직접 만들수 있게 됨.)
constexpr 생성자
constexpr 생성자는 constexpr 함수에서 적용되는 모든 제약조건들이 적용됨.
또한 해당 클래스는 다른 클래스를 가상 상속을 받을 수 없음.
**생성자에 대해서는 추후 나중에 다시 설명.
'Game DevTip > C++' 카테고리의 다른 글
6. C++ string 타입에 대해서 (0) | 2024.12.05 |
---|---|
5. C++ auto & decltype에 대해서. (0) | 2024.12.05 |
4. C++ Typedef(타입 별칭)에 대해서 (0) | 2024.12.05 |
2. C++ const에 대하여 (0) | 2024.12.05 |
1. C++ 변수사용 Tip에 대해서. (0) | 2024.12.05 |
댓글