constexpr 키워드는 C++11에서 도입되고 C++14에서 향상되었습니다.
끊임없는 표현을 의미합니다.
const와 마찬가지로, 변수에 적용될 수 있습니다: 코드가 값을 수정하려고 할 때 컴파일러 오류가 발생합니다.
const와 달리, 함수와 클래스 생성자에도 constexpr을 적용할 수 있습니다.
constexpr는 값 또는 반환 값이 상수이며 가능한 경우 컴파일 타임에 계산됨을 나타냅니다.
템플릿 인수 및 배열 선언과 같이 constexpr 정수가 필요한 곳마다 const 정수 값을 사용할 수 있습니다. 그리고 런타임이 아닌 컴파일 시간에 값이 계산되면 프로그램이 더 빠르게 실행되고 메모리를 덜 사용하는 데 도움이 됩니다.
컴파일 타임 상수 계산의 복잡성과 컴파일 시간에 대한 잠재적 영향을 제한하기 위해 C++14 표준에서는 상수 식의 형식을 리터럴 형식이어야 합니다.
구문
constexpr리터럴 형식식별자=상수식;
constexpr리터럴 형식 식별자{상수식};
constexpr리터럴 타입식별자(params);
constexprctor(params);
매개 변수
params
하나 이상의 매개 변수로, 각 매개 변수는 리터럴 형식이어야 하며 그 자체가 상수 식이어야 합니다.
반환 값
constexpr 변수 또는 함수는 리터럴 형식을 반환해야 합니다.
constexpr 변수
const와 constexpr 변수의 주요 차이점은 const 변수의 초기화가 런타임까지 지연될 수 있다는 것입니다.
constexpr 변수는 컴파일 시간에 초기화되어야 합니다. 모든 constexpr 변수는 const입니다.
변수가 리터럴 형식을 갖고 초기화되면
constexpr을 사용하여 선언할 수 있습니다. 생성자가 초기화를 수행하는 경우 생성자를constexpr선언해야 합니다.이 두 가지 조건이 모두 충족되면 참조를
constexpr로 선언할 수 있습니다. 참조된 객체가 상수 표현식으로 초기화되고 초기화 중에 호출된 모든 암시적 변환도 상수 표현식입니다.constexpr변수 또는 함수의 모든 선언에는constexpr지정자가 있어야 합니다.
constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression
constexpr 함수
constexpr 함수는 코드 사용에 필요할 때 컴파일 시간에 반환 값을 계산할 수 있는 함수입니다. 코드를 사용하려면 컴파일 시간에 constexpr 변수를 초기화하거나 비형식 템플릿 인수를 제공하기 위한 반환 값이 필요합니다. 인수가 constexpr값인 경우 constexpr 함수는 컴파일 타임 상수를 생성합니다.
constexpr 이외의 인수를 사용하여 호출하거나 컴파일 시간에 해당 값이 필요하지 않은 경우 일반 함수처럼 런타임에 값을 생성합니다. 이 이중 동작 덕분에 동일한 함수의 constexpr 버전과 constexpr 이외 버전을 작성하지 않아도 됩니다.
constexpr 함수 또는 생성자는 암시적으로 inline합니다.
constexpr 함수에는 다음 규칙이 적용됩니다.
constexpr함수는 리터럴 형식만 사용하고 반환해야 합니다.constexpr함수는 재귀적일 수 있습니다.C++20 이전에는
constexpr함수를 가상으로 설정할 수 없으며 바깥쪽 클래스에 가상 기본 클래스가 있는 경우와 같이 생성자를constexpr로 정의할 수 없습니다. C++20 이상에서는constexpr함수가 가상일 수 있습니다. Visual Studio 2019 버전 16.10 이상 버전은constexpr이상 컴파일러 옵션을 지정할 때/std:c++20가상 함수를 지원합니다.본문은
= default또는= delete로 정의할 수 있습니다.본문에는
goto문이나try블록이 포함될 수 없습니다.constexpr이 아닌 템플릿의 명시적 전문화는constexpr로 선언될 수 있습니다.constexpr템플릿의 명시적인 전문화는constexpr일 필요도 없습니다.
Visual Studio 2017 이상의 constexpr 함수에는 다음 규칙이 적용됩니다.
여기에는
if및switch문과for, 범위 기반for,while및 do-while를 포함한 모든 반복 문이 포함될 수 있습니다.여기에는 지역 변수 선언이 포함될 수 있지만 변수는 초기화되어야 합니다. 리터럴 형식이어야 하며
static또는 스레드 로컬일 수 없습니다. 로컬로 선언된 변수는const일 필요가 없으며 변경될 수 있습니다.constexpr비정적 멤버 함수는 암시적으로static일 필요는 없습니다.
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
팁
Visual Studio 디버거에서 최적화되지 않은 디버그 빌드를 디버깅할 때 내부에 중단점을 넣어 constexpr 함수가 컴파일 시간에 평가되고 있는지 여부를 알 수 있습니다. 중단점이 적중되면 런타임에 함수가 호출되었습니다. 그렇지 않은 경우 컴파일 시간에 함수가 호출되었습니다.
extern constexpr
/Zc:externConstexpr 컴파일러 옵션을 사용하면 컴파일러가 을 사용하여 선언된 변수에 constexpr을 적용합니다. 이전 버전의 Visual Studio에서는 기본적으로 또는 /Zc:externConstexpr-이 지정된 경우 constexpr 키워드가 사용되는 경우에도 Visual Studio에서 extern 변수에 내부 링크를 적용합니다.
/Zc:externConstexpr 옵션은 Visual Studio 2017 업데이트 15.6부터 사용할 수 있으며 기본적으로 꺼져 있습니다.
/permissive- 옵션은 /Zc:externConstexpr을 사용하도록 설정하지 않습니다.
예시
다음 예에서는 constexpr 변수, 함수 및 사용자 정의 형식을 보여 줍니다.
main()의 마지막 문에서 constexpr 멤버 함수 GetValue()는 값이 컴파일 시간에 알려질 필요가 없기 때문에 런타임 호출입니다.
// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>
using namespace std;
// Pass by value
constexpr float exp(float x, int n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp(x * x, n / 2) :
exp(x * x, (n - 1) / 2) * x;
}
// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
return n == 0 ? 1 :
n % 2 == 0 ? exp2(x * x, n / 2) :
exp2(x * x, (n - 1) / 2) * x;
}
// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
return N;
}
// Recursive constexpr function
constexpr int fac(int n)
{
return n == 1 ? 1 : n * fac(n - 1);
}
// User-defined type
class Foo
{
public:
constexpr explicit Foo(int i) : _i(i) {}
constexpr int GetValue() const
{
return _i;
}
private:
int _i;
};
int main()
{
// foo is const:
constexpr Foo foo(5);
// foo = Foo(6); //Error!
// Compile time:
constexpr float x = exp(5, 3);
constexpr float y { exp(2, 5) };
constexpr int val = foo.GetValue();
constexpr int f5 = fac(5);
const int nums[] { 1, 2, 3, 4 };
const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };
// Run time:
cout << "The value of foo is " << foo.GetValue() << endl;
}
요구 사항
Visual Studio 2015 이상 -