C 中的全局初始化顺序:忽略依赖关系
在 C 中,翻译单元内全局变量的初始化顺序是明确定义的。但是,全局变量之间的依赖关系可以被忽略,从而导致令人惊讶的行为。
考虑以下代码:
<code class="cpp">struct Foo; extern Foo globalFoo; struct Foo { Foo() { printf("Foo::Foo()\n"); } void add() { printf("Foo::add()\n"); } static int addToGlobal() { printf("Foo::addToGlobal() START\n"); globalFoo.add(); printf("Foo::addToGlobal() END\n"); return 0; } }; Foo globalFoo; int dummy = Foo::addToGlobal(); int main() { printf("main()\n"); return 0; }</code>
使用 GCC 4.4.3 编译时,预期输出为:
Foo::Foo() Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END main()
这是因为全局变量globalFoo是在调用静态方法Foo::addToGlobal()之前初始化的。但是,如果我们交换 globalFoo 和虚拟声明的顺序,输出将变为:
Foo::addToGlobal() START Foo::add() Foo::addToGlobal() END Foo::Foo() main()
看起来 Foo 的实例方法是在未构造的实例上调用的。这是因为全局初始化的顺序忽略了依赖关系。
为了确保 Foo 的构造函数在初始化 dummy 之前被调用,我们需要确保在同一翻译单元中 globalFoo 在 dummy 之前定义。或者,我们可以使用指向全局实例的静态指针,该指针在任何动态初始化之前将被初始化为 null。然后 addToGlobal 方法可以检查指针是否为空,并在必要时创建全局 Foo。
以上是为什么在 C 中交换全局变量声明会导致意外行为?的详细内容。更多信息请关注PHP中文网其他相关文章!