C 全局初始化顺序:探索依赖关系
在 C 中,翻译单元中的全局变量通常按照声明的顺序进行初始化。但是,在考虑跨多个翻译单元的初始化顺序时,可能会出现混乱。
初始问题场景
考虑以下代码:
<code class="cpp">struct Foo { Foo() { printf("Foo::Foo()\n"); } void add() { printf("Foo::add()\n"); } static int addToGlobal() { globalFoo.add(); return 0; } }; Foo globalFoo; int dummy = Foo::addToGlobal(); int main() { printf("main()\n"); return 0; }</code>
与这段代码,预期的输出是:
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
但是,交换 dummy 和 globalFoo 的声明和初始化会产生不同的输出:
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
初始化顺序和依赖关系
此行为表明全局变量的初始化顺序忽略了依赖关系。在这种情况下,对 Foo::addToGlobal() 的调用尝试在调用其构造函数之前访问 Foo 的方法。
解决方案:确保正确的初始化
为了确保 Foo 的构造函数在 dummy 初始化之前被调用,我们可以在同一翻译单元中在 dummy 之前定义 globalFoo。这保证了 globalFoo 将首先被初始化,从而允许 addToGlobal() 成功访问其方法。
替代解决方案:静态初始化守卫
或者,我们可以引入静态Foo::addToGlobal() 内的初始化保护:
<code class="cpp">static Foo* pFoo = nullptr; if (pFoo == nullptr) { pFoo = &globalFoo; } pFoo->add();</code>
此检查确保指针 pFoo 在访问其方法之前已初始化为 globalFoo,有效防止过早使用 globalFoo。
以上是如何保证C中具有依赖关系的全局变量的正确初始化?的详细内容。更多信息请关注PHP中文网其他相关文章!