请考虑以下代码:
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
即内部联系。这意味着每个翻译单元都有自己的副本。
由于上面的内联函数依赖于这些常量,这些函数中的哪一个(如果有的话)是正确的?
答案 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_a2
和f_b2
无效。 f_b1
也无效,因为ostream
的{{1}}输出运算符通过引用获取其参数;即使它按值获取其参数,隐式调用的复制构造函数也会通过引用获取其参数。 std::string
是正常的,因为f_a1
stream-out运算符按值获取其参数,并且复制int
的值不是odr-use。