この前、 Exceptional C++ 読んだ時にメモしておこうと思って忘れてたので今度こそ。

例外安全における重要な保証

  1. 基本的な保証 : リソースをリークしないこと。
  2. 強い保証 : 例外発生前の (参照やイテレータといった) プログラムの状態にロールバックできること。
  3. nothrow 保証 : 完全に例外を投げないこと。とくにデストラクタや swap 関数はこれが必要。

標準例外規則

  1. デストラクタ・operator deleteは例外を投げない。つまり throw() を指定すること。(補足:C++11以降は noexcept キーワードを使うとわかりやすい)
  2. RAII イディオムを常用し、リソースの所有と管理を分離すること。
  3. 例外を投げる可能性がある箇所(リソース確保、コピーなど)を全て、別個の関数で安全に処理すること。

以上は「例外安全」の説明です。これとは別に「例外中立」という概念もあります。それぞれの定義は

  • 例外安全 : 例外が発生しても適切に処理する (メモリリーク無し、例外発生前と一貫性を保つ = ロールバックする)
  • 例外中立 : 全ての例外を呼び出し側に伝える (捕捉して握りつぶさない)

例外中立を実現するには try/catch を除去するリソース管理の技法(copy&swapなど)が紹介されています。なお、例外安全と例外中立は、標準ライブラリのコンテナに保証される性質です。この本は例外処理以外にもいろんな規則 (Liskov Substitution Principle とか) やイディオム (pimpl とか) がでてきて、いかに C++ が複雑な言語か思い知らされる本です。補足として、現在ではこの本の中心となる nothrow 保証な swap 関数を実装する他に move semantics を利用する手もあります。

参考