C++ constexpr 与静态常量:更喜欢哪一个?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/41125651/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
constexpr vs. static const: Which one to prefer?
提问by Mr.C64
For defining compile-time constantsof integral types like the following (at function and class scope), which syntax is best?
对于定义如下整数类型的编译时常量(在函数和类范围内),哪种语法最好?
static const int kMagic = 64; // (1)
constexpr int kMagic = 64; // (2)
(1)
works also for C++98/03 compilers, instead (2)
requires at least C++11. Are there any other differences between the two? Should one or the other be preferred in modern C++ code, and why?
(1)
也适用于 C++98/03 编译器,而不是(2)
至少需要 C++11。两者之间还有其他区别吗?在现代 C++ 代码中应该首选一个还是另一个,为什么?
EDIT
编辑
I tried this sample code with Godbolt's CE:
我用Godbolt 的 CE尝试了这个示例代码:
int main()
{
#define USE_STATIC_CONST
#ifdef USE_STATIC_CONST
static const int kOk = 0;
static const int kError = 1;
#else
constexpr int kOk = 0;
constexpr int kError = 1;
#endif
return kOk;
}
and for the static const
case this is the generated assembly by GCC 6.2:
对于这种static const
情况,这是 GCC 6.2 生成的程序集:
main::kOk:
.zero 4
main::kError:
.long 1
main:
push rbp
mov rbp, rsp
mov eax, 0
pop rbp
ret
On the other hand, for constexpr
it's:
另一方面,因为constexpr
它是:
main:
push rbp
mov rbp, rsp
mov DWORD PTR [rbp-4], 0
mov DWORD PTR [rbp-8], 1
mov eax, 0
pop rbp
ret
Although at -O3
in both cases I get the same (optimized) assembly:
尽管-O3
在这两种情况下我都得到了相同的(优化的)程序集:
main:
xor eax, eax
ret
EDIT #2
编辑#2
I tried this simple code (live on Ideone):
我试过这个简单的代码(在 Ideone 上直播):
#include <iostream>
using namespace std;
int main() {
const int k1 = 10;
constexpr int k2 = 2*k1;
cout << k2 << '\n';
return 0;
}
which shows that const int k1
is evaluated at compile-time, as it's used to calculate constexpr int k2
.
这表明它const int k1
是在编译时计算的,因为它用于计算constexpr int k2
.
However, there seems to be a differentbehavior for double
s. I've created a separate question for that here.
但是,s似乎有不同的行为double
。我创建为一个单独的问题在这里。
采纳答案by AnT
As long as we are talking about declaring compile-time constants of scalarinteger or enum types, there's absolutely no difference between using const
(static const
in class scope) or constexpr
.
只要我们谈论声明标量整数或枚举类型的编译时常量,使用const
(static const
在类范围内) 或constexpr
.
Note that compilers are required to support static const int
objects (declared with constant initializers) in constant expressions, meaning that they have no choice but to treat such objects as compile-time constants. Additionally, as long as such objects remain odr-unused, they require no definition, which further demonstrates that they won't be used as run-time values.
请注意,编译器需要支持static const int
常量表达式中的对象(用常量初始值设定项声明),这意味着它们别无选择,只能将此类对象视为编译时常量。此外,只要此类对象保持 odr-unused,它们就不需要定义,这进一步表明它们不会用作运行时值。
Also, rules of constant initializationprevent local static const int
objects from being initialized dynamically, meaning that there's no performance penalty for declaring such objects locally. Moreover, immunity of integral static
objects to ordering problems of static initialization is a very important feature of the language.
此外,常量初始化规则会阻止static const int
动态初始化本地对象,这意味着在本地声明此类对象不会造成性能损失。此外,整数static
对象对静态初始化排序问题的免疫力是该语言的一个非常重要的特征。
constexpr
is an extension and generalization of the concept that was originally implemented in C++ through const
with a constant initializer. For integer types constexpr
does not offer anything extra over what const
already did. constexpr
simply performs an early check of the "constness" of initializer. However, one might say that constexpr
is a feature designed specifically for that purpose so it fits better stylistically.
constexpr
是最初在 C++ 中通过const
常量初始化器实现的概念的扩展和概括。对于整数类型constexpr
并没有提供比const
已经做过的任何额外的东西。constexpr
简单地对初始化程序的“一致性”进行早期检查。但是,有人可能会说这constexpr
是专门为此目的而设计的功能,因此它在风格上更适合。
回答by Guillaume Racicot
constexpr
variable is guaranteed to have a value available at compile time. whereas static const
members or const
variable could either mean a compile time value or a runtime value. Typing constexpr
express your intent of a compile time value in a much more explicit way than const
.
constexpr
变量保证在编译时有一个可用的值。而static const
成员或const
变量可能意味着编译时值或运行时值。键入constexpr
以比const
.
One more thing, in C++17, constexpr
static data member variables will be inline too. That means you can omit the out of line definition of static constexpr
variables, but not static const
.
还有一件事,在 C++17 中,constexpr
静态数据成员变量也将被内联。这意味着您可以省略static constexpr
变量的行外定义,但不能省略static const
.
As a demand in the comment section, here's a more detailed explanation about static const
in function scope.
作为评论区的需求,这里有更详细的static const
in function scope的解释。
A static const
variable at function scope is pretty much the same, but instead of having a automatic storage duration, it has static storage duration. That mean it's in some way the equivalent of declaring the variable as global, but only accessible in the function.
static const
函数作用域中的变量几乎相同,但它没有自动存储持续时间,而是具有静态存储持续时间。这意味着它在某种程度上相当于将变量声明为全局变量,但只能在函数中访问。
It is true that a static
variable is initialize at the first call of the function, but since it's const
too, the compiler will try to inline the value and optimize out the variable completely. So in a function, ifthe value is known at compile time for this particular variable, then the compiler will most likely optimize it out.
确实,static
在第一次调用函数时会初始化变量,但由于const
也是如此,编译器将尝试内联该值并完全优化该变量。所以在一个函数中,如果这个特定变量的值在编译时是已知的,那么编译器很可能会优化它。
However, if the value isn't known at compile time for a static const
at function scope, it might silentlymake your function (a very small bit) slower, since it has to initialize the value at runtimethe first time the function is called. Plus, it has to check if the value is initialized each time the function is called.
但是,如果在编译时不知道 atstatic const
函数作用域的值,它可能会默默地使您的函数(非常小的一点)变慢,因为它必须在第一次调用函数时在运行时初始化该值。另外,每次调用该函数时,它都必须检查该值是否已初始化。
That's the advantage of a constexpr
variable. If the value isn't known at compile time, it's a compilation error, not a slower function. Then if you have no way of determine the value of your variable at compile time, then the compiler will tell you about it and you can do something about it.
这就是constexpr
变量的优点。如果该值在编译时未知,则是编译错误,而不是较慢的函数。然后,如果您无法在编译时确定变量的值,那么编译器会告诉您有关它的信息,您可以对此做一些事情。