const 与非常量内联变量

const vs non-const inline variables

假设我有以下两个文件:

test.cpp

inline double pi { 3.1415 };
#include <iostream>

void test() {

    std::cout << pi << std::endl;

}

main.cpp

inline double pi { 2.178 };

void test();

#include <iostream>

int main() {

    std::cout << pi << std::endl;
    test();

}

inline 变量默认有外部链接。因此,我最初的想法是,根据单一定义规则 (ODR),同一个变量可以在多个翻译单元中声明,只要该变量声明为内联并且包含 相同的确切定义

所以我的第一个问题是,即使变量是内联声明的,但它们在翻译单元中有不同的定义,为什么这个程序可以编译?

其次,inline non-const 和 inline const 变量有什么区别?

例如,如果您运行上面的代码,您应该得到以下输出

2.178
2.178

但是,如果您转到两个文件并将 pi 设为 const double,即 inline const double pi {3.1415}inline const double pi {2.178}

您得到以下输出:

2.178
3.1415

这里到底发生了什么?

您的程序有未定义的行为,原因与您给出的完全相同。

您的工具链不需要诊断未定义的行为,而且在通常难以 "spot" 的情况下(其中很多),它甚至不会打扰。充其量,链接器( 而不是 编译器)可以在构建期间发现这种特殊情况,如果编写它的人认为这足以保证额外的工作和构建时间。

但是,不:这条规则属于程序员的责任范畴。你违反了规则,现在你的程序也以复杂的方式被破坏了,我们可能会利用有关你的计算机、工具链、月相、心情、鞋子颜色和程序组装的足够信息来解决这些问题……但这实际上没有任何意义值。

添加 const 可能会导致编译器( 而不是 链接器)在某些地方将 "references" 省略到此变量,字面意思是 "inlining"使用时的初始化值,作为优化。当它知道值不会因初始化而改变时(感谢 const),它可以这样做。结果是您不再从未定义的行为中观察到如此多的怪异,因为您从程序中看到的行为更多地受限于各个翻译单元。