杀死魔术数字:“ const int” vs“ constexpr int”(或最后没有区别)

Cha*_*onX 13 c++ const magic-numbers constexpr

假设我有一个magic number想要摆脱的...

//whatever.cpp

for (int i = 0; i < 42; i++)
{
    //...
}
Run Code Online (Sandbox Code Playgroud)

我可以通过两种方式杀死它:

在源文件中带有const int SOMETHING_SOMETHING_MEANING_OF_LIFE = 42
或带有。constexpr int SOMETHING_SOMETHING_MEANING_OF_LIFE = 42
.cpp

在这种情况下,两者之间是否有任何有意义的区别(我记得编译器推断出-在任何一种情况下-值均未更改,因此42实际上将其硬编码在结果循环/展开循环/任何机器代码中)或归结为个人品味吗?

在一个相关的问题中:如果magic number在标头(.h)文件而不是源(.ccp)文件中声明了(从而替换它的事物),那会发生什么变化(如果是,则如何改变)呢?

Vit*_*meo 17

const int仅当从一个常量表达式初始化时,才可以将其用作常量表达式的一部分,但不能保证它是常量表达式的一部分。

const int i = 42; // OK, usable in a constant expression
int j = 42;
const int k = j;  // OK, not usable in a constant expression
Run Code Online (Sandbox Code Playgroud)

constexpr int确保变量的初始化程序是一个常量表达式,否则程序将无法编译。

constexpr int i = 42; // OK, usable in a constant expression
int j = 42;
constexpr int k = j;  // Compile-time error, 'j' is not a constant expression
Run Code Online (Sandbox Code Playgroud)

因此,如果要确保初始化程序确实是一个常量表达式constexpr则是更好的选择。

  • 非常感谢您的出色回答 - 这是我希望可以接受两个答案的情况之一*叹息* (2认同)

Aco*_*orn 12

在这种情况下,两者之间是否有任何有意义的区别(我记得编译器推断出-在任何一种情况下-值都不会改变,而是实际上将42硬编码到结果循环/展开循环/任何代码中),或者归结为个人品味?

如上所示,代码生成不会有任何区别。

但是,不同之处在于,constexpr变量可确保在编译时知道该值。请参阅@VittorioRomeo的答案。

constexpr如果它确实是一个编译时值,也可以编写,出于文档目的:当某人阅读您的代码并看到时constexpr,他们会自动知道它是一个真正的固定值。在初始化很重要的情况下(例如,调用函数),这一点很重要。

您还可以将constexpr变量视为包含文字(例如#define FOO 123)的C宏的真正替代。

最后,请记住constexpr暗示const

在一个相关的问题中:如果在头文件中而不是.ccp文件中声明了幻数(及其替换物),会发生什么变化?

不会。但是,如果要在头文件中声明全局变量,则可能要在上使用inline(在C ++ 17中可用)constexpr,以便程序中只有一个实体,这是避免出现的优势ODR问题,并可能节省内存和初始化时间。

请参阅标头中的const和constexpr变量应该内联以防止违反ODR吗?想要查询更多的信息。