我知道在不同的翻译单元(例如,不同的cpp / lib / dll / so文件)中定义的静态变量的初始化顺序是未定义的。这是否意味着以下程序的行为没有明确定义?
#include <vector>
std::vector<int> v;
int main()
{
v.push_back(1);
}
编辑:这里我以STL向量为例。但它可能是任何其他“第三方”课程的对象。因此,我们不知道该对象是否通过其他全局变量初始化。这意味着在C ++中,使用非平凡的构造函数创建一个单一的全局对象是不安全的。正确?
答案 0 :(得分:8)
不,因为当您在main中使用v时,它是完美定义的。静态初始化阶段在main ...中使用v之前发生。
如果在不同的翻译单元中使用2个全局变量并且两者之间存在依赖关系,则会出现问题。有关说明,请参阅此C++ FAQ lite。常见问题解答中的下一项解释了如何避免“惨败”。
静态初始化的问题使得C ++中的全局变量比任何其他语言都差。好的库编写者知道问题并避免静态订单初始化惨败。即使没有,如果图书馆传播得很好,有人会遇到问题,我希望能解决它。但是第三方库并不总是写得很好,它们可以是一个由C ++程序员无知的新公司编写的库......
所以,是的,这是不安全的,你是对的。而在C ++中,避免使用全局变量甚至超过其他语言!
注意:Columbo指出,标准并没有确切地说v是在进入main之前定义的(参见他的回答)。你的实例没有实际区别。
答案 1 :(得分:6)
在[basic.start.init] / 4中指定:
它是实现定义的动态初始化 具有静态存储持续时间的非局部变量在之前完成 主要的第一个声明。如果初始化推迟到某些 在主要的第一个陈述之后的时间点,它应该在之前发生 第一个odr-use(3.2)中定义的任何函数或变量 与要初始化的变量相同的翻译单元。
因此定义v
在首次使用此翻译单元的任何功能之前进行初始化,包括main
。这意味着在此特定程序中v
在main
的第一个语句之前初始化。
当不同翻译单元中的多个变量取决于其初始化的相对顺序时,会发生static initialization order fiasco;初始化可以相对于彼此不确定地排序,这取决于它们的初始化。
答案 2 :(得分:0)
由于只定义了一个全局对象,因此初始化只能有一个顺序,因此没有问题。