다음 정의 사이에 차이점이 있습니까?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
그렇지 않다면 C ++ 11에서 어떤 스타일이 선호됩니까?
답변
차이가 있다고 생각합니다. 더 쉽게 이야기 할 수 있도록 이름을 바꾸겠습니다.
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
모두 PI1
와 PI2
당신이 그들을 수정할 수 없습니다 의미 상수입니다. 그러나 단지 PI2
컴파일 타임 상수이다. 그것은 해야 컴파일시에 초기화 될 수있다. PI1
컴파일 타임 또는 런타임에 초기화 될 수 있습니다. 또한 컴파일 타임 상수가 필요한 컨텍스트 에서만 PI2
사용할 수 있습니다. 예를 들면 다음과 같습니다.
constexpr double PI3 = PI1; // error
그러나:
constexpr double PI3 = PI2; // ok
과:
static_assert(PI1 == 3.141592653589793, ""); // error
그러나:
static_assert(PI2 == 3.141592653589793, ""); // ok
어느 쪽을 사용해야합니까? 필요에 맞는 것을 사용하십시오. 컴파일 타임 상수가 필요한 상황에서 사용할 수있는 컴파일 타임 상수가 있는지 확인 하시겠습니까? 런타임에 수행 된 계산으로 초기화 할 수 있습니까? 기타.
답변
여기에는 차이가 없지만 생성자가있는 형식이있을 때 중요합니다.
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
상수이지만 컴파일 타임에 초기화되지는 않습니다. s1
로 표시 constexpr
되므로 상수이며 S
의 생성자도 표시 되므로constexpr
있으므로 컴파일 타임에 초기화됩니다.
대부분 런타임에 초기화하는 데 시간이 많이 걸리고 컴파일러로 작업을 푸시하려고 할 때 중요합니다.이 작업은 시간이 많이 걸리지 만 컴파일 된 프로그램의 실행 시간을 늦추지는 않습니다.
답변
constexpr 은 상수이며 컴파일 중에 알려진 값을 나타냅니다.
const 는 상수 인 값을 나타냅니다. 컴파일하는 동안 반드시 알아야하는 것은 아닙니다.
int sz;
constexpr auto arraySize1 = sz; // error! sz's value unknown at compilation
std::array<int, sz> data1; // error! same problem
constexpr auto arraySize2 = 10; // fine, 10 is a compile-time constant
std::array<int, arraySize2> data2; // fine, arraySize2 is constexpr
const는 constexpr과 동일한 보장을 제공하지 않습니다. const 객체는 컴파일 중에 알려진 값으로 초기화 될 필요가 없기 때문입니다.
int sz;
const auto arraySize = sz; // fine, arraySize is const copy of sz
std::array<int, arraySize> data; // error! arraySize's value unknown at compilation
모든 constexpr 객체는 const이지만 모든 constexpr 객체는 constexpr이 아닙니다.
컴파일러가 변수에 컴파일 타임 상수가 필요한 컨텍스트에서 사용할 수있는 값을 갖도록하려면, 도달 할 도구는 const가 아닌 constexpr입니다.
답변
constexpr 기호 상수는 컴파일 타임에 알려진 값을 제공해야합니다. 예를 들면 다음과 같습니다.
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
constexpr int c2 = n+7; // Error: we don’t know the value of c2
// ...
}
컴파일 타임에는 알려지지 않았지만 초기화 후에도 변경되지 않는 값으로 초기화되는 “변수”의 값을 처리하기 위해 C ++은 두 번째 형태의 상수 ( const )를 제공합니다. 예를 들어 :
constexpr int max = 100;
void use(int n)
{
constexpr int c1 = max+7; // OK: c1 is 107
const int c2 = n+7; // OK, but don’t try to change the value of c2
// ...
c2 = 7; // error: c2 is a const
}
이러한“ const 변수”는 다음 두 가지 이유로 매우 일반적입니다.
- C ++ 98에는 constexpr이 없었으므로 사람들은 const을 사용했습니다 .
- 상수 표현식은 아니지만 (컴파일 타임에 값을 알 수없는) 변수 “목록 변수”는 초기화 후에 값을 변경하지 않는 것이 그 자체로 널리 유용합니다.
참조 : Stroustrup의 “프로그래밍 : C ++을 사용한 원리 및 실습”