在Ubuntu上运行c ++。
在configuration.h文件中我有这个(全局):
static const string APP_CONFIG_FILE_NAME = "cfg";
在我的configuration.cpp中(顺便说一下是单例,所以配置的构造函数调用了加载配置)我这样做:
void Configuration::loadConfiguration() {
cout<< "config file name " << APP_CONFIG_FILE_NAME.data();
load();
}
将从另一个全局调用负载配置:(这是失败的关键点)
Timer t(Configuration::Instance()->timeout);
我看到费用字符串未初始化(空)。如果我用char *替换字符串,它以我预期的顺序初始化。
但是在另一个程序中,配置工作的相同类,所以我不知道问题。
还有另外一个问题,但不一样,因为there它不是全球性的。
答案 0 :(得分:8)
当然,它会被初始化。但是,它很可能按照您不希望/期望初始化的顺序进行初始化。
具体来说,它可能不是在您使用它时构建的,因为您在构建另一个全局时使用它。
不幸的是,您没有很好的方法可移植指定全局数据的初始化顺序。标准未定义多个文件之间的初始化顺序,尽管可能由工具链指定。因此,使用另一个工具链改变编译或构建的顺序可能导致不同的初始化顺序。搜索“静态初始化顺序惨败”以获取更多详细信息。
避免此问题的一种方法是在函数中声明静态数据:
const std::string& AppConfigFileName() {
static const std::string name("cfg");
return name;
}
虽然......我不明白为什么它必须是静态的(上面的函数允许你按值返回 - 不需要静态)。另外,我不明白为什么这不是一个简单的C字符串,因为你只是把它当作配置加载器中的C字符串。
答案 1 :(得分:2)
关键问题是调用Configuration::loadConfiguration
时。该
>> 翻译单元之间的初始化顺序是未定义的,所以
如果从{的构造函数调用Configuration::loadConfiguration
另一个翻译单元中的静态对象,该变量可能没有
已建成。在这种特殊情况下,最简单的解决方案是
只是将类型更改为char const[]
;这允许静态
初始化,在任何动态初始化之前发生。 (任何
涉及非平凡构造函数的初始化是动态的。)
更一般地说,您可以使用单例模式作为字符串。
其他几点也值得一提:
您已在头文件中声明了一个static
对象实例。
这意味着每个翻译单元都包含头文件
将有一个单独的对象实例。这可能不是一个
好主意。
您输出APP_CONFIG_FILE_NAME.data()
。这只是数据
std::string
对象 - 不保证为'\0'
终止。当您需要'\0'
终止字符串时,您必须使用
std::string::c_str()
。 (但在这种情况下,你可以输出
std::string
。它不需要任何函数调用。)