更多 C++ 惯用法/首次使用时构造
外观
确保在对象第一次使用之前对其进行初始化。具体来说,确保非局部静态对象在其第一次使用之前被初始化。
延迟构造/求值
具有非平凡构造函数的静态对象必须在使用之前初始化。如果未采取适当的措施,则可能会在非局部静态对象初始化之前访问它。
struct Bar {
Bar () {
cout << "Bar::Bar()\n";
}
void f () {
cout << "Bar::f()\n";
}
};
struct Foo {
Foo () {
bar_.f ();
}
static Bar bar_;
};
Foo foo;
Bar Foo::bar_;
int main () {}
在上面的代码中,Bar::f() 在其构造函数被调用之前被调用。应该避免这种情况。
有两种可能的解决方案,取决于所考虑对象的析构函数是否具有非平凡的析构语义。将原本是静态的对象封装在一个函数中,以便该函数在使用之前对其进行初始化。
- 使用动态分配在首次使用时构造
struct Foo {
Foo () {
bar().f ();
}
Bar & bar () {
static Bar *b = new Bar ();
return *b;
}
};
如果对象具有具有非平凡语义的析构函数,则使用局部静态对象代替动态分配,如下所示。
- 使用局部静态在首次使用时构造
struct Foo {
Foo () {
bar().f ();
}
Bar & bar () {
static Bar b;
return b;
}
};
- 单例模式的实现通常使用这种惯用法。
- 自适应通信环境 (ACE) 中的 ACE_TSS<T> 类模板用于在线程特定存储 (TSS) 中创建和访问对象,它使用这种惯用法。