全局对象本质上是不安全的?

qua*_*ell 3 c++

我知道在不同的翻译单元(例如,不同的cpp/lib/dll/so文件)中定义的静态变量的初始化顺序是未定义的.这是否意味着以下程序的行为没有明确定义?

#include <vector>

std::vector<int> v;

int main()
{
    v.push_back(1);
}
Run Code Online (Sandbox Code Playgroud)

编辑:这里我用STL矢量作为例子.但它可能是任何其他"第三方"课程的对象.因此,我们不知道该对象是否通过其他全局变量初始化.这意味着在C++中,使用非平凡的构造函数创建一个单一的全局对象是不安全的.对?

neu*_*uro 8

不,因为当您在main中使用v时,它是完美定义的.静态初始化阶段在主要使用v之前发生...

如果在不同的翻译单元中使用2个全局变量并且两者之间存在依赖关系,则会出现问题.有关解释,请参阅此C++ FAQ lite.常见问题解答中的下一个项目解释了如何避免'惨败'.

静态初始化的问题使得C++中的全局变量比任何其他语言都差.好的库编写者知道问题并避免静态订单初始化惨败.即使没有,如果图书馆传播得很好,有人会遇到问题,我希望能解决它.但是第三方库并不总是写得很好,它们可以是一个由C++程序员无知的新人在你公司编写的库......

所以,是的,这是不安全的,你是对的.而在C++中,避免全局变量甚至超过其他语言!

注意:Columbo指出,标准并没有确切地说v是在进入main之前定义的(参见他的回答).你的实例没有实际区别.


Col*_*mbo 6

它在[basic.start.init]/4中指定:

实现定义是否在第一个main语句之前完成具有静态存储持续时间的非局部变量的动态初始化.如果初始化的主要的第一条语句后推迟到某个时间点,它应以同样的转换单元中定义为要初始化的变量的任何函数或变量的第一ODR使用(3.2)前发生.

因此,定义v在首次使用该翻译单元的任何功能之前进行初始化,包括main.这意味着在这个特定的程序v中,在第一个语句之前初始化main.

静态初始化顺序的悲剧发生时多个变量不同的翻译单位取决于初始化它们的相对顺序; 初始化可以相对于彼此不确定地排序,这取决于它们的初始化.