本文へスキップ
BecomeCoder

C++コース · 第17章 例外処理とモダンな機能 · レッスン68

標準例外と例外安全

ローカル実施

導入

C++ には、用途別の標準例外クラスが用意されています。自分で投げるときも受けるときも、これらを土台にすると分かりやすくなります。あわせて「例外が起きても壊れない」コードの考え方に触れます。

この回は読み物です(例外の送出を含むため)。コードは手元の環境(g++ / clang など)で試してください。

説明

標準例外はすべて std::exception を親に持ち、<stdexcept> によく使うものがそろっています。catch (const exception& e) と親で受ければ、種類を問わずまとめて捕まえられます。

flowchart TB
  E["std::exception(すべての親)"]
  E --> L["logic_error<br/>(プログラムの論理ミス)"]
  E --> R["runtime_error<br/>(実行時の問題)"]
  L --> IA["invalid_argument"]
  L --> OR["out_of_range"]
  R --> OF["overflow_error"]
#include <iostream>
#include <vector>
#include <stdexcept>
using namespace std;

int main() {
    vector<int> v = {1, 2, 3};
    try {
        cout << v.at(10) << endl;   // at は範囲外で out_of_range を投げる
    } catch (const out_of_range& e) {
        cout << "範囲外: " << e.what() << endl;
    } catch (const exception& e) {   // それ以外の標準例外もまとめて
        cout << "その他: " << e.what() << endl;
    }
    return 0;
}

catch は上から順に試され、最初に合ったものが使われます。より具体的な型を上、const exception& を下に置くのが定石です。前章のスマートポインタや vector を使っていれば、例外で途中脱出しても資源は自動で解放されます(これが「例外安全」の土台)。

まとめ

標準例外は std::exception を頂点とする階層で、<stdexcept>out_of_range などを使います。catch は具体的な型を上・const exception& を下に。RAII(スマートポインタ・vector)を使えば、例外が飛んでも資源が漏れない「例外安全」なコードになります。