2013-02-07 3 views
8

XCode 4.6を使用してMac OS Xでテスト済みです。リストの_first_要素を削除すると `.rend()`が無効になるのはなぜですか?

この例のコードは、私が予想通りstd::list作品の最後の要素を削除する例を示しますlist::end()へのイテレータの参照は、まだ「終わり過去1」であると、まださえ最後の要素の除去による有効です。

しかし、2番目の例は私の直感とは対照的です。 最初ののリストを削除するlist::rend()私は「最初の1」と考えていました。

私の期待は間違っていましたか?なぜ間違っていたのですか?最後の要素の削除による「1を過ぎて」という参照は有効なままですが(?ではありません)、最初の要素の先頭にある「1」の参照は無効になります。

void printList(list<int>& os) 
{ 
    for(int& i : os) 
    printf("%d ", i) ; 
    puts(""); 
} 

void testList() 
{ 
    list<int> os ; 
    os.push_back(1) ; 
    os.push_back(2) ; 
    os.push_back(3) ; 
    os.push_back(4) ; 
    os.push_back(5) ; 

    // Forward iterators: reference to .end() not invalidated when remove last elt. 
    list<int>::iterator fwdEnd = os.end() ; 
    printList(os) ; 
    os.erase(--os.end()) ; // remove the 5 (last elt) 
    printList(os) ; 
    if(fwdEnd == os.end()) puts("YES, fwdEnd==os.end() still, iterators not invalidated") ; // I get __this__ result 
    else puts("NO: fwdEnd INVALIDATED") ; 



    list<int>::reverse_iterator revEnd = os.rend() ; 
    // remove the front element 
    printList(os) ; 
    os.erase(os.begin()) ; // removes the 1 
    printList(os) ; 
    if(revEnd == os.rend()) puts("YES revEnd is still valid") ; 
    else puts("NO: revEnd NOT valid") ; // I get __this__ result 
} 
+0

私がそれを理解する方法は、逆の反復子は、それが一見指摘しているものを指摘しません。 「最初のものを1つ」とすると、逆イテレータは、先頭を参照する通常のインターレーターをラップします。ラップされたイテレータが無効になると、逆イテレータも無効になります。しかし、私はこれを裏付ける基準からの引用を持っていません。 – hvd

+0

私は他の質問があると思います:* "最初の例で' 'rbegin''が同様に無効になっていますか?* * – user7116

答えて

16

これはリバースイテレータは、通常のイテレータよりもわずかに異なる参照ロジックを有するという事実によるものである:それは要素を指すが、逆参照するとき、それは前の要素への参照を生成

以下を試してみると、簡単にこれを見ることができます:

#include <vector> 
#include <iostream> 
#include <algorithm> 

using namespace std; 

int main() 
{ 
    vector<int> v = { 1, 2, 3, 4, 5, 6 }; 
    auto i = find(begin(v), end(v), 3); 
    cout << *i << endl; 

    vector<int>::const_reverse_iterator ri(i); 
    cout << *ri << endl; 
} 

出力は次のようになります

3 
2 

リバースイテレータ特定の要素へ物理点、それは論理点、それに先行する要素です。したがって、逆反復子は、物理的にインデックスi-1と間接参照インデックスi、収率(参照)要素と、コレクション内の要素を指している:これは、理由は

     i, *i 
         | 
    -  1  2  3  4  5  6  - 
       |  | 
       *ri ri 

理由実際rend()によってイテレータリターンコレクション内の最初の要素を指し、最初の要素の前の要素を指しません。したがって、最初の要素を削除すると無効になります。

  begin, *begin      end, *end 
      |         | 
    -  1  2  3  4  5  6  - 
    |  |        |  | 
*rend  rend     *rbegin  rbegin 

これはリストにのみ適用されるものではなく、双方向イテレータを提供するすべてのコレクションに適用されます。

+2

グレートダイアグラム! – StilesCrisis

+0

@StilesCrisis:ありがとうございました:-) –

+0

実際の要素はありません "先頭に1"というものがあります。順方向イテレータは実際には "1"を指していますが、逆方向イテレータは先頭を指しています。逆参照されると、「先頭から1つ先」を指します。 – bobobobo

関連する問題