跳轉到內容

更多 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) 中建立和訪問物件,它使用這種慣用法。
[編輯 | 編輯原始碼]

參考資料

[編輯 | 編輯原始碼]
華夏公益教科書