以下定义之间是否存在差异?
const double PI = 3.141592653589793;
constexpr double PI = 3.141592653589793;
如果没有,在C ++ 11中首选哪种样式?
答案 0 :(得分:281)
我相信存在差异。让我们重命名它们,以便我们可以更容易地讨论它们:
const double PI1 = 3.141592653589793;
constexpr double PI2 = 3.141592653589793;
PI1
和PI2
都是常量,这意味着您无法修改它们。但是仅 PI2
是编译时常量。 必须在编译时初始化。 PI1
可以在编译时或运行时初始化。此外, only PI2
可以在需要编译时常量的上下文中使用。例如:
constexpr double PI3 = PI1; // error
但:
constexpr double PI3 = PI2; // ok
和
static_assert(PI1 == 3.141592653589793, ""); // error
但:
static_assert(PI2 == 3.141592653589793, ""); // ok
至于哪个应该使用?使用符合您需求的任何一种。您是否希望确保您具有可在需要编译时常量的上下文中使用的编译时常量?您是否希望能够在运行时进行计算来初始化它?等
答案 1 :(得分:69)
这里没有区别,但是当你有一个具有构造函数的类型时,这很重要。
struct S {
constexpr S(int);
};
const S s0(0);
constexpr S s1(1);
s0
是一个常量,但它不保证在编译时初始化。 s1
标记为constexpr
,因此它是常量,因为S
的构造函数也标记为constexpr
,它将在编译时初始化。
大多数情况下,这很重要,因为在运行时初始化会非常耗时,并且您希望将该工作推送到编译器上,这也很耗时,但不会减慢编译程序的执行时间
答案 2 :(得分:37)
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,但并非所有const对象都是constexpr。
如果您希望编译器保证变量具有可以的值 在需要编译时常量的上下文中使用的工具是constexpr,而不是const。
答案 3 :(得分:13)
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 变量”非常常见,原因有两个:
参考:&#34;编程:使用C ++的原理和实践&#34;通过Stroustrup