先頭へ戻る

例外 解答ページ | Programming Place Plus C++編【言語解説】 第32章

Programming Place Plus トップページC++編

先頭へ戻る

C++編で扱っている C++ は 2003年に登場した C++03 という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14 -> C++17 -> C++20 と更新されており、今後も 3年ごとに更新されます。
なかでも C++11 での更新は非常に大きなものであり、これから C++ の学習を始めるのなら、C++11 よりも古いバージョンを対象にするべきではありません。特に事情がないなら、新しい C++ を学んでください。 当サイトでは、C++14 をベースにした新C++編を作成中です。

問題①

問題① std::vector で要素をアクセスする際、[]演算子を使うと範囲外アクセスのチェックは行われず、atメンバ関数を使うと、範囲外アクセス時に std::out_of_range例外を送出します。範囲外アクセス時に、呼び出し側でエラーメッセージを出力したい場合、それぞれどのようなコードになりますか?


#include <iostream>
#include <vector>

int main()
{
    std::vector<int> v;
    v.push_back(0);
    v.push_back(1);
    v.push_back(2);

    const std::vector<int>::size_type index = 3;

    if (0 <= index && index < v.size()) {
        std::cout << v[index] << std::endl;
    }
    else {
        std::cerr << "範囲外アクセス" << std::endl;
    }

    try {
        std::cout << v.at(index) << std::endl;
    }
    catch (const std::out_of_range& e) {
        std::cerr << e.what() << std::endl;
    }
}

実行結果

範囲外アクセス
invalid vector subscript

[]演算子の場合、if文による事前チェックが必要になります。今回のような例なら、どういうチェックをすればいいか分かりますが、関数の種類によっては、チェックすべき条件が分からないこともあり得ます。

また、チェックを忘れた場合に、範囲外アクセスを行ったときの動作は未定義なので、バグの発見が遅れたり、難しかったりするかもしれません。

atメンバ関数の場合は、事前チェックは不要です。その場で適切にエラー処理を行うためには、try~catch が必要になりますが、すべての例外を捕捉する catchブロックを、プログラム全域に仕掛けておけば、(範囲外アクセスすること自体が低確率でない限り)確実に問題を捕まえられます。たとえば、

#include <iostream>
#include <vector>

int main()
{
    try {
        std::vector<int> v;
        v.push_back(0);
        v.push_back(1);
        v.push_back(2);

        const std::vector<int>::size_type index = 3;

        if (0 <= index && index < v.size()) {
            std::cout << v[index] << std::endl;
        }
        else {
            std::cerr << "範囲外アクセス" << std::endl;
        }

        std::cout << v.at(index) << std::endl;
    }
    catch (...) {
        std::cerr << "何らかの例外が捕捉されていません。" << std::endl;
    }
}
範囲外アクセス
何らかの例外が捕捉されていません。


参考リンク

更新履歴

’2016/10/30 新規作成。



第32章のメインページへ

C++編のトップページへ

Programming Place Plus のトップページへ



はてなブックマーク に保存 Pocket に保存 Facebook でシェア
Twitter でツイート Twitter をフォロー LINE で送る
rss1.0 取得ボタン RSS 管理者情報 プライバシーポリシー