C++静态全局非POD:理论与实践

rpg*_*rpg 9 c++ qt static initialization shared-libraries

我正在阅读Qt编码惯例文档并发现以下段落:

任何具有一个构造或需要运行的代码来被初始化不能用作库代码全局对象,因为它当该构造/代码将运行是未定义的(在第一次使用,在库负荷,main()之前或者不在所有).即使为共享库定义了初始化程序的执行时间,在插件中移动该代码或者静态编译库时也会遇到麻烦.

我知道这个理论说的是什么,但我不理解"根本不是"部分.有时我使用非POD全局const静态(例如:QString),它从来没有发生过我们可能没有被初始化...这是特定于共享对象/ DLL吗?这只会发生在破碎的编译器上吗?

您如何看待这条规则?

sbi*_*sbi 10

"根本不"部分简单地说C++标准对此问题保持沉默.它不了解共享库,因此没有说明某些C++特性与这些特性的交互.

在实践中,我已经看到在Windows,OSX以及许多版本的Linux和其他Unices上使用的全局非POD静态全局变量,无论是在GUI和命令行程序中,还是作为插件和独立应用程序.至少有一个项目(使用非POD静态全局变量)具有这些项目的所有组合的完整集合的版本.我见过的唯一问题是,一些非常古老的GCC版本生成的代码在可执行文件停止时调用动态库中的此类对象的dtors,而不是在卸载库时.当然,这是致命的(图书馆代码在图书馆已经消失时被调用),但这已经差不多十年了.

但当然,这仍然不能保证任何事情.


Mar*_*ork 6

我认为使用带有构造函数的全局对象没有问题。

它们不应该在构造函数(或析构函数)中对其他全局对象有任何依赖。

但是,如果它们确实具有依赖项,则依赖对象必须位于同一编译单元中或延迟评估,以便您可以在使用它之前强制评估它。

构造函数中的代码也不应该依赖于它的执行时间(这与依赖项有关,但不完全相同),但是您可以安全地假设它至少会被构造(就在调用方法之前) ) 并且 C++ 保证销毁顺序与实例化顺序相反。

遵守这些规则并不是那么困难。