在调用之间清空自身的全局向量

Global vector emptying itself between calls?

本文关键字:全局 向量 调用 之间 清空      更新时间:2023-10-16

我有一个向量在头部,像这样:

extern std::vector<Foo> g_vector;

在相关的cpp文件中有如下内容:

std::vector<Foo> g_vector;

我也有一个类Bar,在它的构造函数中,它会添加一些东西到g_vector,像这样:

Bar::Bar(/* stuff */)
{
    // do things
    std::cout << g_vector.size() << std::endl;
    g_vector.push_back(somefoo);
    std::cout << g_vector.size() << std::endl;
}

如果我在一个函数中声明一个Bar,就像一个理智的人,它似乎工作得很好。但是,如果我想在函数之外声明Bar,就会发生奇怪的事情。例如,我在MyFile1.cpp和MyFile1.cpp中声明了一个Bar,并且由于我在Bar中的cout语句,我可以看到Foo被推入向量,但是当下一个Bar运行其构造函数时,向量的大小再次为0。换句话说,我的输出是

0
1
0
1

给了什么?只是为了额外的双重确定,我还尝试打印出&g_vector,以确保它实际上是push_back进入正确的向量,并且地址都匹配。不管它的价值是什么,这些东西放到向量上的顺序是什么都没关系。我不关心初始化顺序或其他。

不确定问题到底是什么,但我想下面的模式将有助于解决这个问题:定义全局变量的访问器,并将其分配为静态函数变量,如下所示。

头文件:

std::vector<Foo> &getGlobalVector();

在cpp文件:

std::vector<Foo> &getGlobalVector()
{
  static std::vector<Foo> s_vector;
  return s_vector;
}

此模式的灵感来自Andrei Alexandrescu在现代c++设计中的"泛型单例"实现。

我已经养成了系统地使用这个模式的习惯,每当我在维护现有的应用程序时遇到一个现有的全局变量(或者在极少数情况下,我实际上选择自己使用一个全局变量),它可能有助于消除上述应用程序中一些难以重现的bug。

无论如何,这确实有助于避免任何多次初始化或初始化顺序相关的问题。

全局值初始化顺序未定义

阅读这里的静态初始化失败。

当你在函数中声明Bar时,g_vector将在程序运行之前被初始化,因为它承诺在程序运行之前被初始化。如果Bar是一个全局变量,那么你就有问题了。