全局静态常量字符串不会初始化

global static const string won't get initialized

本文关键字:初始化 字符串 静态 常量 全局      更新时间:2023-10-16

在Ubuntu上运行c++。

在configuration.h文件中,我有这个(全局):

static const string APP_CONFIG_FILE_NAME = "cfg";

在我的configuration.cpp(顺便说一句,它是单例的,所以加载配置是由configuration的构造函数调用的)中,我这样做:

void Configuration::loadConfiguration() {
    cout<< "config file name "  << APP_CONFIG_FILE_NAME.data();
        load();
}

负载配置将从另一个全局调用:(这是故障的关键点)

Timer t(Configuration::Instance()->timeout);

我发现开销字符串没有初始化(为空)。如果我用char*替换字符串,它将按预期顺序初始化。

然而,在另一个程序上,同样的类用于配置工作,所以我不知道这个问题。

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

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

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

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

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

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

尽管。。。我不明白为什么这必须是静态的(上面的函数允许您按值返回——不需要静态)。另外,我不明白为什么这不能是一个普通的C字符串,因为你只是在配置加载程序中把它当作一个C字符串。

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

其他几点也值得一提:

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

  • 您输出APP_CONFIG_FILE_NAME.data()。这只是中的数据CCD_ 6对象—不能保证为''终止。当您需要以''结尾的字符串时,必须使用std::string::c_str()。(但在这种情况下,您可以直接输出CCD_ 10。不需要任何函数调用。)