More C++ Idioms/初回使用時生成(Construct On First Use)
出典: フリー教科書『ウィキブックス(Wikibooks)』
目次 |
[編集]
初回使用時生成(Construct On First Use)
[編集] 意図
最初に使用される前に、オブジェクトが初期化されることを保証する。 特に、非ローカル静的オブジェクトに対して保証する。
[編集] 別名
遅延生成・評価
[編集] 動機
自明でない(non-trivial)コンストラクタを持つ静的オブジェクトは使用前に初期化されねばならない。十分な注意を払わないと、初期化されていない非ローカル静的オブジェクトをアクセスしてしまう場合がある。
struct Bar { Bar () { cout << "Bar::Bar()\n"; } void f () { cout << "Bar::f()\n"; } }; struct Foo { Foo () { bar_.f (); } static Bar bar_; }; Foo f; Bar Foo::bar_; int main () {}
上記コードでは、Bar::f() が Bar のコンストラクタより前に呼び出される。これは避けるべきである。
[編集] 解法とサンプルコード
対象オブジェクトのデストラクタが自明(trivial)な挙動を持つかどうかによって、2つの解法がありうる。自明なデストラクタを持つ場合には、静的オブジェクトを関数でくるみ、使用前に関数内で初期化する。
- 動的割り当てによる初回使用時生成(Construct on first use)
struct Foo { Foo () { bar().f (); } Bar & bar () { static Bar *b = new Bar (); return *b; } };
オブジェクトが自明ではない(non-trivial)デストラクタを持つ場合には、以下に示すように動的割り当ての代わりにローカルな静的オブジェクトを用いる。
- ローカル静的オブジェクトによる初回使用時生成(Construct on first use)
struct Foo { Foo () { bar().f (); } Bar & bar () { static Bar b; return b; } };
[編集] 既知の利用
- シングルトン(Singleton)パターンの実装はしばしばこのイディオムを使用する。
- Adaptive Communication Environment (ACE) に存在し、スレッド占有記憶域(thread specific storage (TSS)) 中にオブジェクトを作成、また、アクセスするためのクラステンプレート ACE_TSS<T> はこのイディオムを使用する。