Pet*_*her 1 c++ stdmap object-construction
我多次发现,当在类中将 std::map 声明为静态内联(C++ 17)时,
struct MyStruct
{
static inline std::map <A, B> mymap;
MyStruct(A& a, B& b)
{
mymap[a] = b;
}
};
Run Code Online (Sandbox Code Playgroud)
如果较早调用 MyStruct 构造函数,即在 main 之前、在第一次使用映射成员时调用,它将会崩溃。
如果 std::map 以不同的方式声明,即
struct MyStruct
{
static std::map <A, B>& mymap()
{
static std::map <A, B> map;
return map;
}
MyStruct(A& a, B& b)
{
mymap()[a] = b;
}
};
Run Code Online (Sandbox Code Playgroud)
那么就不会发生崩溃。
我本以为在这两种情况下,都会在允许继续调用 MyStruct 构造函数之前初始化映射。
谁能解释这里发生了什么?
static inline有效地声明类成员ODR在形成最终可执行文件的某个随机选择的翻译单元中定义该类成员。
此时,当以您所描述的方式在翻译单元中引用类成员时,静态初始化顺序失败就成为一个因素。
这会导致未定义的行为。
函数范围的static类实例是一种众所周知的技术,可以克服静态初始化顺序的失败。函数范围的static对象具有明确定义的初始化语义:第一次从任何翻译单元调用函数时。