C++編で扱っている C++ は 2003年に登場した C++03
という、とても古いバージョンのものです。C++ はその後、C++11 -> C++14
-> C++17 -> C++20 -> C++23 と更新されています。
なかでも 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;
.push_back(0);
v.push_back(1);
v.push_back(2);
v
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;
.push_back(0);
v.push_back(1);
v.push_back(2);
v
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;
}
}
範囲外アクセス
何らかの例外が捕捉されていません。
新規作成。
Programming Place Plus のトップページへ
はてなブックマーク に保存 | Pocket に保存 | Facebook でシェア |
X で ポスト/フォロー | LINE で送る | noteで書く |
RSS | 管理者情報 | プライバシーポリシー |