C++ 为什么不需要通过内联函数进行静态初始化
下面的代码片段来自3.6.2/3 N3797 C++14最终工作草案:C++ 为什么不需要通过内联函数进行静态初始化,c++,initialization,C++,Initialization,下面的代码片段来自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
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
不是一个常量表达式
)。我的问题如下:
为什么不要求通过内联函数进行静态初始化 在这种情况下,函数被标记为
inline
这一事实实际上没有太大变化。inline
关键字的唯一实际效果是告诉编译器/链接器接受该函数的多个定义可能会出现在整个程序中(当将所有目标文件链接在一起时),这是直接在头文件中定义函数时所需的,头文件可能包含多个翻译单元(cpp文件)。这是一种对ODR(一个定义规则)进行例外的方法,对于要在标题中定义的函数,我们称之为“内联定义”(或“内联函数”)如果你查看C++的标准,你会发现大多数提到的<>代码>内联关键字正在讨论与提供内联定义(即实现声明的函数而不是单独的CPP文件)有关的问题。
几乎所有定义可供编译器使用的函数都可以作为“函数内联”(与“内联定义”不同)的候选函数但是,这纯粹是编译器做出的优化选择,而不是一个要求。在C++标准中提到函数内联的唯一时间是为了明确说明,如果编译器选择内联函数,则它对代码的行为不会有任何明显的影响(它们都是类似的注释:“这应该是真的,即使函数是内联的”)。inline
关键字和“函数内联”之间的唯一关系是,在标准中,该关键字也可以被视为暗示该函数需要函数内联(因为它通常是),但这不是一个要求,我相信许多编译器在决定是否内联函数时完全忽略了这一点(大多数情况下,因为编译器不需要这一提示,他们完全有能力自己做出选择)
也就是说,您的示例中的
d1
变量是通过调用一个不是constexpr
函数的函数来初始化的,这意味着它不能被要求静态地完成。只有当该函数被标记为constexpr
时,编译器才必须尝试静态地对其求值,从而导致错误该调用中非局部变量的可能静态初始化。将函数标记为inline
在这种情况下没有任何区别,因为除了ODR的应用外,需要内联函数的行为(至少表面上)与任何其他函数相同。因为您的函数调用不是一个常量表达式
?@Plasmah,但函数调用后缀表达式在编译期间将函数体替换为内联函数。您完全误解了内联
关键字的作用。它不会以任何方式强制编译对于内联函数,它是为了内联,甚至被大多数编译器忽略。答案详尽无遗。但是你能得到标准参考,内联函数的ODR异常描述吗?@DmitryFucintv描述内联函数ODR异常的子句是n3337版本(C++11)中的7.1.2/4.对于我的其余评论,只需搜索“inline”一词,您就会在标准中找到与此相关的所有相关评论。