常量vs constexpr上的variables
以下定义有区别吗?
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
至于你应该使用哪个? 使用符合您的需求的任何一个。 你想确保你有一个编译时间常量,可以在需要编译时常量的上下文中使用吗? 你想能够在运行时进行计算来初始化它吗? 等等。
这里没有什么区别,但是当你有一个具有构造函数的types时,它就很重要。
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的,但并不是所有的const对象都是constexpr。
如果你希望编译器保证一个variables的值可以在需要编译时常量的上下文中使用,那么要达到的工具是constexpr,而不是const。
一个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 // ... }
为了处理一个“variables”的值,该variables的初始值是在编译时不知道的,但在初始化后永远不会改变,C ++提供了第二种forms的常量( 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 }
这种“ 常量variables”非常普遍,原因有二:
- C ++ 98没有constexpr,所以人们使用const 。
- 列表项“variables”不是常量expression式(它们的值在编译时是未知的),但在初始化后不改变值本身是非常有用的。