29

ベクトルの値を取得したい場合は、2 つのオプションを使用できます。[] 演算子を使用します。または、関数 .at を使用して例を使用することもできます。

vector<int> ivec;
ivec.push_back(1);

これで両方できるようになりました

int x1 = ivec[0];
int x2 = ivec.at(0); // or

そのオプションを使用すると、これを例外でスローできるため、 at を使用する方が良いオプションだと聞きました。

誰かがこれを説明してもらえますか?

4

4 に答える 4

55

c[i]との違いは、ベクトルの範囲外にある場合に例外c.at(i)at()スローする一方で、単に未定義の動作を呼び出すことです。つまり、何でも起こり得るということです。std::out_of_rangeioperator[]

at()より優れているとは誰も言いませんoperator[]。それは状況に依存します。asat()は範囲チェックを実行しますが、常に望ましいとは限りません。特に、コード自体がインデックスが決して範囲外にならないことを確認している場合はなおさらです。そのような場合は、operator[]より良いです。

次のループを検討してください。

for(size_t i = 0 ; i < v.size(); ++i)
{
   //Should I use v[i] or v.at(i)?
}

このようなループでは、メンバー関数operator[]と比較して常により良い選択です。at()

無効なインデックスの場合に例外をスローして、ブロック内で別の作業を実行できるようにしたいat()場合に使用しcatch{ ...}ます。例外は、通常のコードと例外/代替コードを次のように分離するのに役立ちます。

try
{
   size_t i = get_index(); //I'm not sure if it returns a valid index!

   T item = v.at(i); //let it throw exception if i falls outside range

   //normal flow of code
   //...
}
catch(std::out_of_range const & e)
{
   //alternative code
}

ここで、それが有効なインデックスであることを確認し、代わりに をi呼び出すことができますが、通常のコードと block を使用する代替コードが混在し、コードの通常の流れを読み取ることが難しくなります。上記のように、コードの可読性が向上します。これにより、通常のコードが代替コードから実際に分離され、すっきりとしたクリーンなコードが得られます。operator[]at()if-elsetry-catch

于 2012-06-23T19:00:23.107 に答える
10

との唯一の違いはat、が範囲チェック[]を実行し、実行しないことです。すでに範囲をチェックしているか、範囲外に出られないようにインデックスを構築しており、アイテムに繰り返しアクセスする必要がある場合は、.at[][]at

1 回のチェックと複数回のアクセスの例:

size_t index = get_index(vect);
if (index < 0 || index >= vect.size()) return;
if (vect[index] > 0) {
    // ....
} else if (vect[index] > 5) {
    // ....
} else ....

インデックスが制限内になるように構成されている場合の例:

for (size_t i = 0 ; i != vect.size() ; i++) {
    if (vect[i] > 42) {
        // ....
    }
}
于 2012-06-23T19:00:40.360 に答える
0

at()他の答えは完全に正しいですが、まだデバッグしているコードを書くときに使用するのは良い考えであるという印象を与えるかもしれません。そうするとエラーが通知されるからです。これは一般的なケースですが、ほとんどの普及しているコンパイラには当てはまりません。gccは、デバッグモードにすることで(致命的な)範囲チェックを実行するように設定でき、VisualStudioでも同様のことができます。

于 2012-06-24T10:50:18.083 に答える