37

Windows と Mac の間でクロスプラットフォームのコードを書いています。

list::end() が「リストの最後の要素に続く位置をアドレス指定する反復子を返し」、リストを順方向にトラバースするときにチェックできる場合、逆方向にトラバースする最良の方法は何ですか?

このコードは Mac では機能しますが、Windows では機能しません (最初の要素を超えて減少することはできません)。

list<DVFGfxObj*>::iterator iter = m_Objs.end();
for (iter--; iter!=m_Objs.end(); iter--)// By accident discovered that the iterator is circular ?
{
}

これは Windows で動作します:

list<DVFGfxObj*>::iterator iter = m_Objs.end();
    do{
        iter--;
    } while (*iter != *m_Objs.begin());

forループで実装できる逆方向にトラバースする別の方法はありますか?

4

5 に答える 5

63

reverse_iteratorの代わりに使用しiteratorます。rbegin()&rend()の代わりにbegin()&を使用しend()ます。

マクロを使用したい場合は、Boost 1.36.0 で導入されBOOST_FOREACHたマクロを使用することもできます。BOOST_REVERSE_FOREACH

于 2008-10-09T19:58:08.233 に答える
17

リストを逆に反復する最良/最も簡単な方法は、(既に述べたように) 逆反復子 rbegin/rend を使用することです。

ただし、リバース イテレータは、「現在の」イテレータの位置を 1 つずつ格納するように実装されていることに言及したいと思います (少なくとも標準ライブラリの GNU 実装では)。

これは、実装を単純化するために行われます。これは、逆の範囲が前方の範囲 [begin, end) および [rbegin, rend) と同じセマンティクスを持つようにするためです。

これが意味することは、反復子の逆参照には、毎回新しい一時変数を作成してから減分することが含まれるということです。

  reference
  operator*() const
  {
_Iterator __tmp = current;
return *--__tmp;
  }

したがって、reverse_iterator の逆参照は、通常の反復子よりも遅くなります。

ただし、代わりに通常の双方向反復子を使用して、逆反復を自分でシミュレートし、このオーバーヘッドを回避できます。

for ( iterator current = end() ; current != begin() ; /* Do nothing */ )
{
    --current; // Unfortunately, you now need this here
    /* Do work */
    cout << *current << endl;
}

テストでは、ループの本体で使用される各逆参照について、このソリューションが最大 5 倍高速であることが示されました。

注: std::cout がボトルネックになるため、上記のコードではテストは行われませんでした。

また、注意: std::list のサイズが 1,000 万要素の場合、「ウォール クロック時間」の差は約 5 秒でした。したがって、現実的には、データのサイズがそれほど大きくない限り、rbegin() rend() に固執してください!

于 2008-10-21T20:33:18.520 に答える
14

おそらく逆イテレータが必要です。記憶から:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for( ; iter != m_Objs.rend(); ++iter)
{
}
于 2008-10-09T19:59:55.640 に答える
6

Ferruccio が既に述べたように、reverse_iterator を使用します。

for (std::list<int>::reverse_iterator i = s.rbegin(); i != s.rend(); ++i)
于 2008-10-09T20:05:24.240 に答える
5

これはうまくいくはずです:

list<DVFGfxObj*>::reverse_iterator iter = m_Objs.rbegin();
for (; iter!= m_Objs.rend(); iter++)
{
}
于 2008-10-09T20:05:42.603 に答える