web-dev-qa-db-ja.com

ベクトルを逆方向​​に反復する

終わりから始まりまでのベクトルを反復処理する必要があります。 「正しい」方法は

_for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); rit != v.rend(); ++rit)
{
    //do Something
}
_

DoSomethingが実際のインデックスを知る必要がある場合、index = v.size() - 1 - (rit - v.rbegin)のように、それを取得するためにritを使用していくつかの計算を行う必要があります。

とにかくインデックスが必要な場合は、そのインデックスを使用して反復する方が良いと強く信じています

_for(int i = v.size() - 1; i >= 0; --i)
{
    //do something with v[i] and i; 
}
_

これにより、iが署名され、v.size()が署名されないという警告が表示されます。に変更

for(unsigned i = v.size() - 1; i >= 0; --i)は機能的に間違っています。これは本質的に無限ループであるためです_:)_

私がやりたいことをするための美的に良い方法は何ですか

  • 警告なし
  • キャストは含まれません
  • 過度に冗長ではありません

私は存在しないものを探していないと思います:)

33
Armen Tsirunyan

お気づきのように、符号なしの場合の_i >= 0_の条件の問題は、条件が常にtrueであるということです。 iを初期化するときに1を減算する代わりに、各反復の後にループ条件をチェックした後に1を減算します。

_for (unsigned i = v.size(); i-- > 0; )
_

私はいくつかの理由でこのスタイルが好きです:

  • iはループの最後で_UINT_MAX_にラップアラウンドしますが、その動作には依存しませんrely—タイプが署名されている場合も同様に機能します。署名されていないラップアラウンドに依存することは、私にとって少しハックのように感じます。
  • size()を1回だけ呼び出します。
  • _>=_は使用しません。 forループでその演算子を見つけたら、それを再度読み取って、off-by-oneエラーがないことを確認する必要があります。
  • 条件の間隔を変更する場合は、 "goes to"演算子 を使用するようにできます。
55
Rob Kennedy

他の複数の回答で説明されているように、インデックスを使用してreverse_iteratorループを停止する方法はありません。そうすれば、最小限の追加コストで、// do the work部分で必要に応じてイテレーターまたはインデックスを使用できます。

size_t index = v.size() - 1;
for(std::vector<SomeT>::reverse_iterator rit = v.rbegin(); 
    rit != v.rend(); ++rit, --index)
{
  // do the work
}

インデックスが何のために必要なのか知りたいのですが。 v[index]へのアクセスは、*ritへのアクセスと同じです。

15
Steve Townsend

美的に楽しいです! ;)

for(unsigned i = v.size() - 1; v.size() > i; --i)
5
Nim

解釈が簡単で、インデックス関連のエラーを回避できるため、リバースイテレータバリアントをお勧めします。

時には、単にBOOST_REVERSE_FOREACHを使用すると、コードは次のようになります。

reverse_foreach (int value, vector) {
   do_something_with_the_value;
}

実際には、これらの種類のループに対してはいつでもforeachステートメントを使用できますが、その後は少しわかりにくくなります。

size_t i = 0;

foreach (int value, vector) {
   do_something;
   ++i;
}
2
Yippie-Ki-Yay

しばらくやってみてください:

std::vector<Type> v;
// Some code 
if(v.size() > 0)
{
    unsigned int i = v.size() - 1;
    do
    {
        // Your stuff
    }
    while(i-- > 0);
}
0

こんにちは、最初のサンプルで使用するのと同じようにイテレータを使用する方が良いと思います。イテレータインデックスを取得する必要がある場合は、std :: distanceを使用して計算できます。

0
Sanja Melnichuk

ループ条件i != std::numeric_limits<unsigned>::max() ...または、冗長だと思われる場合は_UINT_MAX_を使用します。または別の方法:
for(unsigned j=0, end=v.size(), i=end-1; j<end; --i, ++j)
または
for(unsigned end=v.size(), i=end-1; (end-i)<end; --i)

0
smerlin