本は少し曖昧です。実行時に現れる未定義の動作であるため、「実行時エラー」ではありません。これは、何でも起こり得ることを意味します。しかし、エラーはプログラムの実行ではなく、厳密にはあなたにあります。実際、未定義の動作を伴うプログラムの実行について話すことさえ不可能であり、賢明ではありません。
C++ には、Java とはまったく異なり、プログラミング エラーから保護するものは何もありません。
@sftrabbit が言うように、std::vector
には代替インターフェイス があり.at()
、これは常に正しいプログラムを提供し (ただし、例外がスローされる場合があります)、その結果、推論できるプログラムになります。
これは C++ の重要な基本的側面であると私は信じているので、例を挙げて要点を繰り返しましょう。ユーザーから整数を読み取っているとします。
int read_int()
{
std::cout << "Please enter a number: ";
int n;
return (std::cin >> n) ? n : 18;
}
ここで、次の 3 つのプログラムを考えてみましょう。
危険なもの:このプログラムの正しさは、ユーザーの入力に依存します! 必ずしも正しくないわけではありませんが、安全ではありません(私が壊れたと呼ぶところまで)。
int main()
{
int n = read_int();
int k = read_int();
std::vector<int> v(n);
return v[k];
}
無条件に正しい:ユーザーが何を入力しても、このプログラムがどのように動作するかはわかっています。
int main() try
{
int n = read_int();
int k = read_int();
std::vector<int> v(n);
return v.at(k);
}
catch (...)
{
return 0;
}
正気のもの:上記のバージョン.at()
は扱いにくいです。チェックしてフィードバックを提供することをお勧めします。動的チェックを実行するため、チェックされていないベクトル アクセスは実際には正常であることが保証されます。
int main()
{
int n = read_int();
if (n <= 0) { std::cout << "Bad container size!\n"; return 0; }
int k = read_int();
if (k < 0 || k >= n) { std::cout << "Bad index!\n"; return 0; }
std::vector<int> v(n);
return v[k];
}
(ベクトルの構築が独自の例外をスローする可能性は無視しています。)
C++ の多くの操作は安全ではなく、条件付きでしか正しくないという教訓がありますが、プログラマーは事前に必要なチェックを行うことが期待されています。言語が代わりにやってくれるわけではないので、お金はかかりませんが、覚えておく必要があります。いずれにせよエラー状態を処理する必要があるため、ライブラリまたは言語レベルで高価で非特定の操作を強制するのではなく、チェックを統合するのに適した立場にあるプログラマーに責任が委ねられるという考えです。とにかく書く必要があるコードに。
皮肉なことを言いたければ、このアプローチを Python と対比させたいと思います。Python では、ユーザーが作成したエラー処理をまったく行わずに、信じられないほど短くて正確なプログラムを作成できます。反対に、プログラマーが意図したものからわずかに逸脱するようなプログラムを使用しようとすると、特定されていない、読みにくい例外とスタック トレースが表示され、何を改善すべきかについてのガイダンスがほとんど得られません。エラー処理を書くことを強制されることはありません。多くの場合、エラー処理は書かれません。(C++ と Java を完全に対比することはできません。Java は一般的に安全ですが、短いJava プログラムはまだ見たことがありません。)</rantmode>