我有一段像这样构造的代码:
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说地图尚未创建。它是如何工作的,我该如何改变呢?
答案 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();
}