全局静态常量字符串赢得';无法初始化 > Ubuntu .< /P>上运行C++

全局静态常量字符串赢得';无法初始化 > Ubuntu .< /P>上运行C++,c++,C++,在configuration.h文件中,我有以下内容(全局): 在我的configuration.cpp(顺便说一句,它是单例的,所以由配置的构造函数调用load configuration)中,我执行以下操作: void Configuration::loadConfiguration() { cout<< "config file name " << APP_CONFIG_FILE_NAME.data(); load(); } 我看到成本字

在configuration.h文件中,我有以下内容(全局):

在我的configuration.cpp(顺便说一句,它是单例的,所以由配置的构造函数调用load configuration)中,我执行以下操作:

void Configuration::loadConfiguration() {
    cout<< "config file name "  << APP_CONFIG_FILE_NAME.data();
        load();
}
我看到成本字符串没有初始化(为空)。如果我用char*替换字符串,它将按我期望的顺序初始化

但是在另一个程序上,相同的类用于配置工作,所以我不知道问题出在哪里


还有一个问题,但不一样,因为它不是全局的。

当然,它会被初始化。但是,它很可能是按照您不希望/预期的顺序初始化的

具体来说,它可能不是在您使用它的时候构建的,因为您在构建另一个全局文件时使用了它

不幸的是,您没有一个好的方法可移植地指定全局数据的初始化顺序。标准中没有定义多个文件之间的初始化顺序,尽管它可能是由工具链指定的。因此,使用另一个工具链更改编译或构建的顺序可能会导致不同的初始化顺序。有关详细信息,请搜索“静态初始化订单失败”

避免此问题的一种方法是在函数中声明静态数据:

const std::string& AppConfigFileName() {
  static const std::string name("cfg");
  return name;
}

虽然…我不明白为什么这必须是静态的(上面的函数允许您按值返回——不需要静态)。另外,我不明白为什么这不能是一个普通的C字符串,因为在配置加载器中将其视为一个C字符串。

关键问题是调用
Configuration::loadConfiguration
时。这个 转换单元之间的初始化顺序未定义,因此 如果从的构造函数调用了
Configuration::loadConfiguration
另一个转换单元中的静态对象,变量可能没有 已经建成。在这种特殊情况下,最简单的解决方案是 只需将类型更改为
char const[]
;这允许静态 初始化,在任何动态初始化之前发生。(任何 涉及非平凡构造函数的初始化是动态的。) 更一般地说,可以对字符串使用单例模式

其他几点也值得一提:

  • 您已经在头文件中声明了对象的
    静态
    实例。 这意味着包括头文件的每个翻译单元 将有一个单独的对象实例。这可能不是个好主意 好主意

  • 您可以输出
    APP\u CONFIG\u FILE\u NAME.data()
    。这只是其中的数据
    std::string
    对象它是而不是
    '\0'
    结束。当需要以
    '\0'
    结尾的字符串时,必须使用
    std::string::c_str()
    。(但在这种情况下,您可以只输出
    std::string
    。不需要对其进行任何函数调用。)


这还不够。提供一个最小的可编译示例,如下所示。我不能,因为它在一个项目中,如果我在一个没有所有复杂内容的干净简单的项目中进行测试,那么它将工作。它可能是静态的,因为他在尝试使用它时遇到了链接器错误,或者没有外部或静态。static修复了他的错误,他保留了它……您是对的,没有理由认为它是静态的(来自javaconstdef的坏习惯)。对于一个全局变量,const和static const之间有什么意义吗?这正是问题所在——“特别是,它可能不是在您使用它的时候构建的,因为您在构建另一个全局变量的过程中使用了它。”,maybee这可能导致具有相同程序的计算机之间的差异。@LuchianGrigore我实际上在问为什么它必须是静态的,不是为了可见性,而是为了生存期。@user1495181好吧,简单地改变编译文件的顺序就足以改变全局文件的初始化顺序。即使通过另一个工具链运行它,也可以生成全局的另一个初始化顺序。
Timer t(Configuration::Instance()->timeout);
const std::string& AppConfigFileName() {
  static const std::string name("cfg");
  return name;
}