2013-02-07 4 views
8

XCode 4.6을 사용하여 Mac OS X에서 테스트되었습니다. 내가 예상대로목록의 _first_ 요소를 제거하면 왜 .rend()가 무효화됩니까?

이 예제 코드는 std::list 작품의 마지막 요소를 제거 보여줍니다 list::end()에 반복자 참조가 여전히 "결국 지난 1"여전히 유효, 심지어 마지막 요소의 제거를 통해 .

그러나 두 번째 예는 내 직관에 맞지 않습니다. 목록의 첫 번째 요소를 제거하면 이 변경되고 list::rend()인데 "처음부터 1 번"이라고 생각합니다.

내 기대가 잘못 되었습니까? 왜 잘못 된거야? 마지막 요소를 삭제하여 "1 끝까지"참조하는 것이 유효합니까? (그렇지 않아야합니까?) 앞 부분을 제거한 후 처음 (.rend()) 앞에 "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

내가 이해하는 방식으로, 역 반복자는 겉보기로 가리키고있는 것을 가리 키지 않습니다. "처음부터 지나간 것"역방향 반복자는 시작을 나타내는 일반적인 중재자를 래핑합니다. wrapped iterator가 무효화 될 때 reverse iterator도 마찬가지이다. 그러나 나는 이것을 뒷받침 할 기준에서 인용문을 가지고 있지 않다. – 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"이라는 실제 element_는 없습니다 .. 앞으로 반복기가 실제로 "1 끝을 가리키고"반면 역방향 반복기는 시작 부분을 가리키고, 역 참조 (dereferenced) 될 때, "처음의 1"을 가리킨다. – bobobobo

관련 문제