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

C++ 全局对象本质上是不安全的?,c++,C++,我知道在不同的转换单元(例如不同的cpp/lib/dll/so文件)中定义的静态变量的初始化顺序是未定义的。这是否意味着后续程序的行为没有得到很好的定义 #include <vector> std::vector<int> v; int main() { v.push_back(1); } #包括 std::向量v; int main() { v、 推回(1); } 编辑:这里我以STL向量为例。但它可能是任何其他“第三方”类别的对象。因此,我们不知道该对

我知道在不同的转换单元(例如不同的cpp/lib/dll/so文件)中定义的静态变量的初始化顺序是未定义的。这是否意味着后续程序的行为没有得到很好的定义

#include <vector>

std::vector<int> v;

int main()
{
    v.push_back(1);
}
#包括
std::向量v;
int main()
{
v、 推回(1);
}

编辑:这里我以STL向量为例。但它可能是任何其他“第三方”类别的对象。因此,我们不知道该对象是否通过其他全局变量初始化。这意味着在C++中,创建一个具有非平凡构造函数的单个全局对象是不安全的。是吗?

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

如果在不同的翻译单元中使用两个全局变量,并且两者之间存在依赖关系,则会出现问题。请看下面的解释。常见问题解答中的下一项解释了如何避免“惨败”

静态初始化问题使得C++中的全局变量比任何其他语言都差。好的库编写人员知道这个问题,避免了静态订单初始化的失败。即使没有,如果图书馆被广泛传播,我希望有人能解决这个问题。但是第三方的LIBs并不总是很好的写,它们可以是一个新的C++程序员编写的在你公司里的图书馆…< /P> 所以,是的,这是不安全的,你是对的。在C++中,避免全局语言比其他语言要多!
注:Columbo as指出,标准并没有明确规定v在进入main之前已定义(见其答案)。实例中没有实际差异。

由于只定义了一个全局对象,因此其初始化只能有一个顺序,因此没有问题

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

实现定义了 具有静态存储持续时间的非局部变量在 主要问题的第一项声明。如果初始化延迟到某个时间 时间点在主节点第一次声明之后,应在 在odr中定义的任何函数或变量的首次使用(3.2) 与要初始化的变量相同的转换单位

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


不同的转换单元中的多个变量取决于它们的相对初始化顺序时,会发生错误;根据初始化情况,初始化可能会彼此不确定顺序。

如果全局变量的构造不依赖于任何其他全局变量,则是安全的。不,顺序未指定,这意味着您不能依赖于以任何特定顺序初始化它们。如果您编写的代码依赖于顺序,则可能(也可能不会)导致未定义的行为。请注意,翻译单元(如您的)中的顺序,如果一个C++程序打算在多个翻译单元中实现,那么它将被认为是任何第三方库中的一个错误,因为它不能跨多个翻译单元工作,所以产生了不确定的行为。(例如,MySql C API)可能要求您在使用函数之前调用
init()
函数。如果向量实现使用自己的全局变量呢?那么v可能是在该变量之后初始化的。@quantum:这就是为什么不应该使用全局变量的原因:)我认为库设计器(很好的一个)不使用全局变量。不管怎样,如果向量使用全局,那么,静态初始化顺序就可能发生。C++标准库使用全局,例如CUT和CIN。@量子:没有人说过它们是好的;事实上,我认为这不是最好的设计。像cout这样的全局服务是访问全局服务的一种简单方式。单身是获得全球服务的更好方式。最好的方法是使用依赖项注入。但是拥有一个全球性的公司更容易。。。