头文件中的内联函数是否可以使用具有内部链接的常量?

时间:2015-02-27 13:17:30

标签: c++ const inline linkage one-definition-rule

请考虑以下代码:

const int a = 0;
const std::string b = "hi";

inline void f_a1()
{
    std::cout << a;
}

inline void f_b1()
{
    std::cout << b;
}

inline void f_a2()
{
    std::cout << &a;
}

inline void f_b2()
{
    std::cout << &b;
}

假设此代码存在于将包含在多个翻译单元中的头文件中。

我对内联函数的理解是它们在每个翻译单元中必须完全相同。

我对上面使用的常量的理解是,它们是隐含的static即内部联系。这意味着每个翻译单元都有自己的副本。

由于上面的内联函数依赖于这些常量,这些函数中的哪一个(如果有的话)是正确的?

1 个答案:

答案 0 :(得分:6)

如果包含在多个翻译单元中,唯一有效的功能是f_a1

相关条款是 [basic.def.odr] / 6,其中指出inline函数可以出现在多个翻译单元中,但仅限于:

  

[...]名称可以指非易失性   如果对象在D的所有定义中具有相同的文字类型,则const具有内部链接或无链接的对象,   并且使用常量表达式(5.19)初始化对象,并且该对象不使用odr,并且   对象在D的所有定义中具有相同的值;

由于对象为const,因此每个 [basic.link] / 3都有内部链接:

  

具有命名空间范围(3.3.6)的名称具有内部链接,如果它是[...]的名称    - 一个非易失性变量,显式声明为const或constexpr,并且都没有显式声明   extern也未声明具有外部联系[...]

但是,获取变量的地址或形成对变量的引用(例如,用于参数传递)是 odr-use ,因此f_a2f_b2无效。 f_b1也无效,因为ostream的{​​{1}}输出运算符通过引用获取其参数;即使它按值获取其参数,隐式调用的复制构造函数也会通​​过引用获取参数。 std::string是正常的,因为f_a1 stream-out运算符按值获取其参数,并且复制int的值不是odr-use。