ikautak.log

C/C++, Python, CUDA, Android, Linux kernel, Network, etc.

More Effective C++ 項目13 参照渡しで例外を受け取る

新訂版 More Effective C++ (AddisonーWesley professional co)

新訂版 More Effective C++ (AddisonーWesley professional co)

  • 作者: スコット・メイヤーズ,安村通晃,伊賀聡一郎,飯田朱美,永田周一
  • 出版社/メーカー: ピアソンエデュケーション
  • 発売日: 2007/06/29
  • メディア: 単行本(ソフトカバー)
  • 購入: 8人 クリック: 129回
  • この商品を含むブログ (43件) を見る

項目13 参照渡しで例外を受け取る

catch節で例外オブジェクトの渡し型を指定するが、選択肢はポインタ渡し、値渡し、参照渡しの3つがある。

ポインタ渡し

ポインタ渡しが最も効率がよいが、catch節に制御が渡ったときも、ポインタの指し示す先に例外オブジェクトが存在することを保証しなければならない。

void someFunction() {
    exception ex;  // ローカルオブジェクト。
                   // この関数のスコープから出たら破棄される。
    ...

    throw &ex;     // これから削除されるオブジェクトのポインタを投げている。
    ...
}
void someFunction() {
    ...
    throw new exception;
    ...
}

こう書くと、catch節では必ずオブジェクトが存在するが、破棄して良いかは判断がつかない。(ヒープ上に割り当てられた例外オブジェクトかどうかわからない)

ポインタで受け取る方法はC++の伝統にも反している。bad_alloc、bad_cast、bad_typeid、bad_exceptionの4つの標準的な例外は全てオブジェクトであり、値か参照でしか受け取れない。

値渡し

値で受け取ると、例外の削除の問題はなくなるが、例外が発生するたびに2度コピーが走る。
また、派生クラスのオブジェクトを基底クラスのオブジェクトとして受け取るとスライスが発生する。
派生クラスのデータは削ぎ落とされ、ポリモーフィズムも働かず、仮想関数は基底クラスのものになる。

参照渡し

参照で受け取ると、ポイント渡しのようなオブジェクト削除の問題もなく、値渡しのようなオブジェクトスライスの問題もない。 例外のコピーも1回で済む。

まとめ
例外は参照渡しで受け取る。