跳转到内容

更多 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) 中创建和访问对象,它使用这种惯用法。
[编辑 | 编辑源代码]

参考资料

[编辑 | 编辑源代码]
华夏公益教科书