下面的代码片段来自3.6.2 / 3 N3797 C ++ 14最终工作草案:
inline double fd() { return 1.0; }
extern double d1;
double d2 = d1; // unspecified:
// may be statically initialized to 0.0 or
// dynamically initialized to 0.0 if d1 is
// dynamically initialized, or 1.0 otherwise
// may be initialized statically or dynamically to 1.0
double d1 = fd();
据我所知,例如,d1和d2的初始化不需要静态完成。 double d2 = d1
非常容易理解(d1
不是constant expression
)。我的问题如下:
为什么不需要静态地通过内联函数进行初始化?
答案 0 :(得分:1)
在这种情况下,函数标记为inline
的事实并没有太大变化。 inline
关键字的唯一实际效果是告诉编译器/链接器接受该函数的多个定义可能出现在整个程序中(将所有目标文件链接在一起时),这在定义时需要直接在头文件中起作用,该头文件可以包含在几个翻译单元(cpp文件)中。对于要在头文件中定义的函数,我们称之为“内联定义”(或“内联函数”),这是关键字获取的位置,这是对ODR(一个定义规则)进行例外处理的一种方法。其名称。如果你仔细阅读C ++标准,你会发现inline
关键字的大多数提及正在讨论与提供内联定义相关的问题(即,实现声明它的函数,而不是单独的cpp文件)。
几乎任何编译器可用定义的函数都可以作为“函数内联”的候选者(这与“内联定义”不同)。但这纯粹是编译器所做的优化选择,并不是必需的。 C ++标准中提到的函数内联的唯一一次是清楚地表明,如果编译器选择内联函数,它不应该对代码的行为产生任何可见的影响(它们都是这样的评论:“这应该是的,即使函数是内联的“)。 inline
关键字和“函数内联”之间的唯一关系是标准中的一个建议,即该关键字也可以被视为暗示函数内联对于该函数是理想的(因为它经常是),但是这不是一个要求,我相信许多编译器在决定是否内联函数时完全忽略它(主要是因为编译器不需要那个提示,它们完全能够自己做出选择)。
也就是说,您的示例中的d1
变量正在通过调用函数来初始化,该函数不是constexpr
函数,这意味着不能要求静态地完成它。只有当函数标记为constexpr
时,编译器才必须尝试静态评估它,从而导致可能从该调用中静态初始化非局部变量。将函数标记为inline
在此上下文中没有任何区别,因为除了ODR的应用之外,内联函数需要表现(至少表面上)与任何其他函数相同。