初始化静态字符串成员
c++: initializing static string members
我在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"。
这是Static Initialization惨败。
根据c++标准,如果在不同的转换单元中声明具有静态存储时间的对象,则不指定初始化顺序。
因此任何依赖于这些对象初始化顺序的代码都注定会失败,这个问题在c++中被称为静态初始化惨败。
你的代码依赖于B::str
和C::str
的初始化发生在D::str
之前的条件,这是标准不保证的。由于这3个静态存储持续时间对象驻留在不同的翻译单元中,它们可以按任意顺序初始化。
如何避免?
解决方案是使用Construct On First use Idiom,简而言之,它意味着用一个通过引用返回对象的全局函数替换全局对象。引用返回的对象应该是local static,因为静态局部对象是在第一次控制流流过它们的声明时构造的,所以对象只会在第一次调用时创建,并且在每次后续调用时都会返回相同的对象,从而模拟您需要的行为。
这应该是一个有趣的阅读:
如何防止"静态初始化顺序惨败"?
静态变量的初始化顺序没有保证。所以不要依赖它。而是使用实际的文字初始化它们,或者更好的方法是,在运行时真正需要它们时初始化它们。
- C++ 字符串类擦除成员函数的时空复杂性
- 无法将字符串数组声明为类成员而不是字符 (C++)
- 使用 const char* 初始化 const ref 字符串成员时幕后会发生什么
- CPPCHECK C++成员函数上的格式字符串
- 无法使用 strcpy 将字符串复制到静态结构成员
- 反转没有循环的字符串,C++中只有 std::string 成员
- 如何删除作为C++联合的成员变量的字符串对象
- 有没有办法把字符串数组成员放在".structurevariable"前面?
- C++-将对象(如字符串)映射到表中成员函数的正确方法
- 将字符串推送到私有成员向量
- 有没有更快的方法从成员函数返回格式化字符串
- 在C++中,从构造函数中将字符串文本分配给成员const char*变量时会发生什么
- 添加字符串类型的类成员会导致调用基类函数而不是子函数
- 分类一个向量,该向量由该类中的成员字符串保存对象
- 如何在C++中将本地字符串数组复制到私有成员字符串数组
- 如何实例化C++成员字符串引用
- 从c++类中获取成员字符串
- 如何将类成员字符串传递给其他类函数时解决"'std::length_error"?
- 将vector中结构体的成员字符串打印到cout流
- 如何返回类中私有成员字符串的值