5

次のように宣言されたベクトルがあります

std::vector<int> MyVector;
MyVector.push_back(5);
MyVector.push_back(6);
MyVector.push_back(7);

for ループでどのように使用すればよいですか?

イテレータで繰り返すことによって?

for (std::vector<int>::iterator it=MyVector.begin(); it!=MyVector.end(); ++it)
{
    std::cout << "Vector element (*it): " << *it << std::endl;
}

またはそのアクセスイテレータによって?

for (std::vector<int>::size_type i=0; i<MyVector.size(); i++)
{
    std::cout << "Vector element  (i) : " << MyVector.at(i) << std::endl;
}

インターネットで見つけた例では、両方が使用されています。すべての条件下で、一方が他方より優れているか? そうでない場合、いつどちらかを優先する必要がありますか?

4

4 に答える 4

5

最初の形式は、標準ライブラリ コンテナーを反復処理するためのより一般的な形式であるため、より一般的で直感的です。コンテナーを変更する必要がある場合、この反復コードは影響を受けません。すべての標準ライブラリ コンテナー タイプで機能するため、より汎用的なコードが得られます。

2 番目の形式でstd::vector::at()は、反復ごとに呼び出されるたびに境界をチェックするため、パフォーマンスに少し悪影響を与える可能性があります。境界チェックが含まれていないため、このオーバーヘッドは最初の形式には存在しませんoperator[]
ただし、巨大なデータを操作していない限り、パフォーマンスの遅れは気付くほどではないことに注意してください。

于 2012-09-24T07:47:33.533 に答える
3

for ループ内で使用するとベクトルのサイズが 2 回チェックされるため (for ループと std::vector::at() の境界チェックで)、使用したstd::vector's [] operator方がおそらく高速です。std::vector::at()

最初の方法は他のコンテナーで使用できるため、コンテナーの種類を変更するときに非常に役立ちます。

C++11 を使用する場合は、範囲ベースのループを使用してください。

于 2012-09-24T07:51:50.090 に答える
2

まず、C++11 を使用している場合は、範囲ベースの for を使用します。

for (auto i : MyVector)
{
    std::cout << i;
}

またはBOOST_FOREACHC++03 では:

BOOST_FOREACH(int& i, MyVector)
{
  std::cout << i;
}

またはstd::copy:

std::copy(MyVector.begin(),
          MyVector.end(), 
          std::ostream_iterator<int>(std::cout, "\n"));

目前の質問についてはat()、インデックスが範囲内にあることを確認し、そうでない場合は例外をスローします。したがって、追加のチェックが必要でない限り、使用しないでください。最初の方法は標準であり、うまく機能します。一部の人々は衒学的であり、それでさえ次のように書いています:

for (std::vector<int>::iterator it=MyVector.begin(), end = MyVector.end(); it!= end; ++it)
{
    std::cout << "Vector element (*it): " << *it << std::endl;
}

上記では、各ループendを呼び出す代わりにイテレータをキャッシュしました。end()これが実際にパフォーマンスの違いを生むかどうかはわかりません。

于 2012-09-24T07:55:51.647 に答える
1

at()「一方が他方より優れている」ということはありません(ほとんど使用したくない場合を除いてat()、エラーから回復するために実際にできることがある場合にのみ適切です)。イテレータとインデックスの使用は、主にスタイルの1つであり、渡すメッセージです。物事を行うためのより慣用的なC++の方法はイテレーターですが、他のバックグラウンド(数学者など)から来た人々は、索引付けがより慣用的であることに気付くでしょう。

本当の違いがあるところがあります:

  • イテレータイディオムは、他のタイプのコンテナで機能します。これは、他のコンテナを使用する可能性が実際にある場合に関連する可能性があります。

  • 索引付けイディオムは、複数の異なるコンテナーに対して単一の索引を使用できます。同じサイズの複数の要素を反復処理している場合vector、インデックス付けのイディオムを使用すると、それぞれの同じ要素にアクセスしていることが明確になりますvector。(繰り返しますが、これは数学的なアプリケーションで最も頻繁に発生するようです。)

  • 最後に、実際にランダムアクセスを実行しているとき、または何らかの方法で要素を計算しているときはいつでも、インデックスを使用する方がおそらくより直感的です。(このような場合は、で計算を行い、最後の瞬間intにのみ変換することをお勧めします。)size_t

于 2012-09-24T08:53:19.297 に答える