在观看一个链接至isocpp.org的C++11教程视频时,我注意到了一些东西:
constexpr int windowWidth{800}, windowHeight{600};
声明这些
int
变量为 constexpr
,而不仅仅是 const
,有何意义?在观看一个链接至isocpp.org的C++11教程视频时,我注意到了一些东西:
constexpr int windowWidth{800}, windowHeight{600};
int
变量为 constexpr
,而不仅仅是 const
,有何意义?很棒的视频Vittorio!
以下是声明 int
const
和 constexpr
之间的区别摘要:
int get_int(); // Some run time function that returns int
template <int N> // example use requiring a compile time int
struct test {};
const int w = get_int(); // initialized at run time
const int x = 5; // initialized at compile time
constexpr int y = get_int(); // error, can not initialize at compile time
constexpr int z = 6; // initialized at compile time
int
main()
{
test<w> tw; // error, w is not a compile time constant
test<x> tx; // ok, x is a compile time constant
test<y> ty; // error, there is no compile time constant named y
test<z> tz; // ok, z is a compile time constant
}
constexpr
时,你要求初始化在编译时发生,否则会出现编译时错误。当你使用const
时,你允许初始化在运行时发生,尽管如果初始化器本身是编译时常量,则仍然会在编译时发生。const int
,代码审查员必须查看初始化(如果这是const int
的副本,则返回到原始值)以知道该const int
是编译时常量还是运行时常量。constexpr int
,代码审查员可以立即假设它是编译时常量,而不需要分析它是如何初始化的。如果这个假设是错误的,编译器将标记它为错误。
<免责声明>
在下面的评论中,Kerrek SB正确指出我在这个答案中使用了术语上的“快速和松散”。我这样做是为了使答案简短易懂。我所说的“在编译时初始化”和“编译时常量”是指标准中第5.19节“常量表达式”[expr.const]所称的整数常量表达式。</免责声明>
const int x = 5;
),没有任意性。唯一的任意性是动态初始化可能被提升到静态阶段。 - Kerrek SBconst int y = z
和 constexpr int y = z
。在回答问题之前,您必须首先确定 z
是否为整数常量表达式。如果 z
不是整数常量表达式,则后者甚至无法编译。 - Howard Hinnant我是这个视频的作者。
意图.
constexpr
清晰地表达了一个编译时不可变值的意图。而const
并不真正意味着编译时不可变值。
这两个修饰符都可以强制转换,但结果会导致未定义行为。查看DyP的评论以获取更多信息。
在使用C++11时,我认为在处理编译时值时首先要想到的关键字不是const
,而应该是constexpr
。
代码没有constexpr
也会完全相同,或者用const
代替constexpr
也是如此。
但当您查看代码并看到constexpr int windowWidth;
时,您可以100%确信这是一个永远不会在运行时更改的不可变常数。
在我的第二个教程视频中(链接),在前三分钟有一个补充说明关于constexpr
,展示了constexpr
函数和更多的constexpr
示例/说明。
const
”是一个修饰符,甚至可以被强制转换掉,因此它并不真正意味着编译时不可变的值。我认为“constexpr
”实际上并不是对象类型的一部分,它只是暗示了“const
”,并对类型和初始化添加了限制。无论是已声明为“const
”还是“constexpr
”的变量都可以被取消常量属性;通过这种非常量路径进行修改会导致未定义行为。重要的是“编译时”,与“constexpr
”不同,“const
”声明的变量可以用在运行时才能确定的值进行初始化。 - dyp