【问题标题】:const vs non-const inline variablesconst 与非 const 内联变量
【发布时间】:2020-04-10 01:31:16
【问题描述】:

假设我有以下两个文件:

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),我最初的想法是,只要将变量声明为内联并包含相同的确切定义,就可以跨多个翻译单元声明同一个变量p>

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

二、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

这里到底发生了什么?

【问题讨论】:

  • 如果这些定义不同,您将违反 ODR。那是UB。
  • 当您将内联变量放入标题中时,您认为会发生什么?链接器不会检查 every 定义是否相同;它只会选择一个并运行它。至于你的第二个问题,如果一个变量是常量并且你从不尝试获取它的地址,那么无论它是否具有外部链接,编译器都可以安全地内联它。
  • @cigien 编译器没有抱怨,这就是为什么我很困惑。
  • @MutatingAlgorithm 没有什么可抱怨的。每个TU都很好。链接器最多可以诊断它。
  • 每个问题一个问题。

标签: c++ c++17 inline linkage


【解决方案1】:

由于您给出的原因,您的程序具有未定义的行为。

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

但是,不:这条规则属于程序员的责任范畴。你打破了规则,现在你的程序也被打破了,以复杂的方式,我们可能可以通过关于你的计算机、工具链、月相、情绪、鞋子颜色和程序组装的足够信息来解决……但这不会真的有任何意义价值。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-07-29
    • 2011-09-16
    • 1970-01-01
    • 2015-05-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多