对于定义整数类型的编译时常量,如下所示(在函数和类范围内),哪种语法最好?
static const int kMagic = 64; // (1)
constexpr int kMagic = 64; // (2)
(1)
也适用于C ++ 98/03编译器,而(2)
至少需要C ++ 11。这两者之间还有其他差异吗?在现代C ++代码中是否应该首选其中一个,为什么?
修改
我使用Godbolt's 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;
}
对于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
另一方面,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
虽然在-O3
两种情况下我得到相同(优化)的程序集:
main:
xor eax, eax
ret
编辑#2
我尝试了这个简单的代码(live on Ideone):
#include <iostream>
using namespace std;
int main() {
const int k1 = 10;
constexpr int k2 = 2*k1;
cout << k2 << '\n';
return 0;
}
显示const int k1
在编译时进行评估,因为它用于计算constexpr int k2
。
但是,double
似乎存在不同的行为。我为here创建了一个单独的问题。
答案 0 :(得分:31)
constexpr
变量在编译时具有可用值。而static const
成员或const
变量可以表示编译时值或运行时值。键入constexpr
以比const
更明确的方式表达编译时间值的意图。
还有一件事,在C ++ 17中,constexpr
静态数据成员变量也将内联。这意味着您可以省略static constexpr
变量的外部定义,但不能省略static const
。
作为评论部分的要求,这里有关于函数范围static const
的更详细说明。
功能范围内的static const
变量几乎相同,但它具有静态存储持续时间,而不是具有自动存储持续时间。这意味着它在某种程度上相当于将变量声明为全局变量,但只能在函数中访问。
确实,static
变量在函数的第一次调用时初始化,但由于它也是const
,编译器将尝试内联值并完全优化变量。所以在一个函数中, if 在编译时知道这个特定变量的值,那么编译器很可能会优化它。
但是,如果在编译时在函数范围内static const
未知该值,则它可能静默使您的函数(非常小的一点)变慢,因为它具有在第一次调用函数时初始化值在运行时。另外,每次调用函数时都必须检查值是否已初始化。
这是constexpr
变量的优势。如果在编译时未知该值,则表示编译错误,而不是较慢的函数。然后,如果你无法在编译时确定变量的值,那么编译器会告诉你它,你可以对它做些什么。
答案 1 :(得分:17)
只要我们讨论声明标量整数或枚举类型的编译时常量,使用const
(static const
之间绝对没有区别在课堂范围内)或constexpr
。
请注意,编译器需要在常量表达式中支持static const int
个对象(使用常量初始化器声明),这意味着他们别无选择,只能将这些对象视为编译时常量。此外,只要这些对象保持未使用状态,它们就不需要定义,这进一步表明它们不会被用作运行时值。
此外,常量初始化的规则会阻止本地static const int
对象动态初始化,这意味着在本地声明此类对象不会造成性能损失。此外,整数static
对象对静态初始化的排序问题的免疫性是该语言的一个非常重要的特征。
constexpr
是概念的扩展和概括,最初是在C ++中通过const
使用常量初始化程序实现的。对于整数类型,constexpr
不会提供const
以外的任何额外内容。 constexpr
只是对&#34; constness&#34;进行早期检查。初始化程序。但是,有人可能会说constexpr
是专为此目的而设计的功能,因此它更符合风格。