c ++:初始化静态字符串成员

时间:2011-09-21 16:01:15

标签: c++ string static

我在c ++中初始化静态字符串成员时遇到了一些问题。我有几个类,每个类都有几个代表id的静态字符串成员。当我通过调用静态函数初始化变量时,一切都很好。但是,当我想要为另一个变量赋值时,它仍然保留空字符串。这段代码有什么问题?

std::string A::id()
{
    std::stringstream sst; 
    sst << "id" << i;           
    i++;
    return sst.str();
}

  std::string B::str = A::id(); //prints "id0";
  std::string C::str = "str"; //prints str


  std::string D::str = B::str; //prints "" <-- what's wrong here?
  std::string D::str2 = C::str; //prints ""

看起来好像我所指的变量(B :: str和C :: str)尚未初始化。但我假设当执行D :: str = B :: str时C :: str最迟被初始化,因此D :: str也应该保存字符串“id0”。

2 个答案:

答案 0 :(得分:10)

这是 Static Initialization Fiasco

根据C ++标准,如果在不同的 Translation units 中声明具有静态存储持续时间的对象的初始化顺序,则不指定。

因此,任何依赖于这些对象的初始化顺序的代码都必然会失败,这个问题在C ++中被称为静态初始化Fiasco

您的代码依赖于B::strC::str的初始化发生在D::str之前的情况,标准无法保证。由于这3个静态存储持续时间对象位于不同的翻译单元中,因此可能会以任何顺序进行初始化。

如何避免?

解决方案是使用 Construct On First Use Idiom ,简而言之,它意味着用全局函数替换全局对象,该对象通过引用返回对象。通过引用返回的对象应该是本地静态,因为静态本地对象是在第一次控制流过它们的声明时构造的,所以该对象将仅在第一次调用时创建,并且在每次后续调用时都创建相同的对象将被返回,从而模拟您需要的行为。


这应该是一本有趣的读物:

<强> How do I prevent the "static initialization order fiasco"?


答案 1 :(得分:3)

静态变量的初始化没有保证。所以不要依赖它。 而是使用实际的文字来初始化它们,或者更好的是,在真正需要时在运行时初始化它们。

相关问题