RAII なオブジェクトの生成は独立したステートメントで
C++ では関数呼び出しの際に引数をどういう順序で評価するかは不定なわけだが、まだ認識が甘かった。単に順序が不定なだけではなく、第1引数を途中まで評価して、それから第2引数を評価して、その後で第1引数の残りの評価を……、みたいなことも許されるらしい。つまり、f(g(h()), i())
という関数呼び出しが h
→ i
→ g
→ f
という順序で評価される可能性がある、ということだ((C++ 標準は、「f
よりも先に g
と i
が評価されること」と「g
よりも先に h
が評価されること」しか定めていない。))。
このため、std::auto_ptr
の生成を引数中でやってはいけない:
- 悪い書き方
-
f(std::auto_ptr<T>(new T()), g());
- 正しい書き方
-
std::auto_ptr<T> temporary( new T() ); f(temporary, g());
new T()
→ g()
→ std::auto_ptr( )
という評価順序になった場合に g()
が例外を送出すると、new T()
で生成されたオブジェクトがリークしてしまう。この話は『Effective C++』の『17項 ―
new
で生成したオブジェクトをスマートポインタに渡すのは、独立したステートメントで行うようにしよう』に載っていて、そこでは std::auto_ptr
ではなく std::tr1::shared_ptr
が題材に取られているが、一般的に言って、リソースの取得から RAII なオブジェクト*1の生成までの間に例外送出があってはならない。したがって、RAII なオブジェクトの生成は、独立したステートメントで行うべきである。Effective C++ 原著第3版 (ADDISON-WESLEY PROFESSIONAL COMPUTING SERIES)
- 作者: スコット・メイヤーズ,小林健一郎
- 出版社/メーカー: ピアソン・エデュケーション
- 発売日: 2006/04/29
- メディア: 大型本
- 購入: 29人 クリック: 411回
- この商品を含むブログ (186件) を見る