2013-02-07 69 views
8

使用XCode 4.6在Mac OS X上進行測試。爲什麼刪除列表的_first_元素使`.rend()`無效?

此示例代碼示出了去除std::list作品的最後一個元素如我所料:一個迭代參照list::end()仍爲「1過去的結束」和仍然有效,甚至通過移除的最後一個元素的。

但第二個例子反駁我的直覺。刪除第一個列表中的元素變化list::rend(),我認爲這是「1過去的開始」。

我的期望錯了嗎?爲什麼錯了?爲什麼通過刪除最後一個元素來引用「1結束後」仍然有效(不應該?),但在去除前面元素後,對起始前面的「1(.rend())」的引用變爲無效?

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

我的理解是,反向迭代器沒有指向它看似指向的東西。 「一開始就有一個」逆向迭代器包裝一個指向開始的正常interator。當包裝迭代器失效時,反向迭代器也是如此。但我沒有從標準中引用來支持它。 – 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,解除引用的時候,產率(與參考)所述元件與索引i-1

     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