什么时候创建全局变量?

时间:2013-10-27 13:52:11

标签: c++ initialization

我有一段像这样构造的代码:

a.cpp:  
    #include "b.hpp"  
    const unsigned a =  create(1);


b.cpp:
    map<int, string> something; // global variable
    unsigned create(unsigned a){
        something.insert(make_pair(a, "somestring"));
        return a;
    }

现在,这引发了一个段错误,valgrind说地图尚未创建。它是如何工作的,我该如何改变呢?

4 个答案:

答案 0 :(得分:10)

C ++没有定义在程序启动期间构造全局变量的顺序。在构造a之前,可以先初始化something,这会导致上述问题。当您开始构建依赖于正在初始化的其他全局变量的全局变量时,您将遇到经典的静态初始化顺序fiasco

修复上述方案的一种简单方法是将something设为静态并将其移至create函数中。

unsigned create(unsigned a)
{
    static map<int, string> something;
    something.insert(make_pair(a, "somestring"));
    return a;
}

这样可以保证在第一次调用something时创建create

答案 1 :(得分:8)

在进入main()之前创建所有全局变量,但c ++标准未指定它们在不同转换单元之间的构造顺序。它们在同一翻译单元中的构造顺序符合规范。

你可以形成一个由标准保证的东西。像这样:

map<int, string>& mymap(){
    static map<int, string> something;
    return something;
}

unsigned create( unsigned a ) {
    mymap().insert(make_pair(a, "somestring"));
    return a;
}

第一次调用函数mymap()时会创建map。

答案 2 :(得分:3)

标准未定义来自不同翻译单元(即位于不同的* .cpp文件中)的全局变量被初始化的顺序。因此,依赖它是undefined behaviour。另见:

答案 3 :(得分:2)

创建全局变量(即命名空间范围内的变量)的顺序为:

  • 它们在翻译单元中出现的顺序
  • 未指定,从一个翻译单元到另一个翻译单元

这是带有模块的语言不会受到影响,但不幸的是C ++中的常见问题。使用函数本地静态变量,可以在首次使用时进行初始化,这通常可以解决这个问题。

静态本地示例:

int func(int a) {
    static std::map<int, int> m;
    return m[a] = m.size();
}