内联函数访问静态?

时间:2013-03-05 21:34:21

标签: c++ static inline

Section 16.4 of C++ FAQs (2nd Edition) (Paperback) by Marshall P. Cline, Greg Lomow表示内联函数无法安全访问静态数据成员,因为可以在初始化静态数据成员之前调用该函数。

我不明白为什么这适用于内联函数,而不仅仅是其他翻译单元中调用另一个翻译单元中的静态数据成员的任何函数?我没有看到“内联”在这场灾难中起什么作用?

1 个答案:

答案 0 :(得分:6)

在执行相同翻译单元(或多或少的cpp文件)中的任何函数之前,

static个变量已完全初始化。如果main位于不同的翻译单元中,则无法保证在调用main之前初始化它们。 inline函数是重复的,每个翻译单元都有自己的副本。这意味着,与static变量不同的转换单元中的内联函数可能会在正确初始化之前尝试读取/写入该变量,从而导致未定义的行为。 (这些规则非常复杂,但这是我记得的)

  

§3.6.2/ 4实现定义了具有静态存储持续时间的非局部变量的动态初始化是否在main的第一个语句之前完成。如果初始化延迟到第一个main语句之后的某个时间点,它应该在与要初始化的变量相同的转换单元中定义的任何函数或变量的第一个odr-use(3.2)之前发生。

  

§3.2/ 3内联函数应在每个使用它的翻译单元中定义。

据我所知,

内联函数实际上并不比非内联函数危险。访问不同TU中的静态的任何函数都存在风险,并且由于inline恰好将函数放在每个 TU中,因此大多数函数都不安全。一种解决方法是使用"construct on first use idiom"

隐式模板特化很复杂,但为了完整性:

  

§14.7.1/ 3 [temp.inst]静态数据成员的初始化(以及任何相关的副作用)不会发生,除非静态数据成员本身以需要定义静态的方式使用数据成员存在。

因此,模板类的静态成员在使用前总是被初始化。

上述所有内容均受the static initialization order fiasco)约束,其中所述“首次使用idom的构造”解决了这一问题。