-->

为什么删除列表无效`.rend()`的_first_元素?(Why does removing th

2019-07-19 14:23发布

使用的XCode 4.6测试在Mac OS X上。

此示例代码显示移除的最后一个元素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
}

Answer 1:

这是由于一个反向迭代比常规迭代一个略有不同的参考逻辑的事实:它指向的元素,但解除引用的时候,它产生到前一元素的引用。

你会很容易地看到这一点,如果你尝试以下操作:

#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

这并不只适用于列表,但它提供了双向迭代所有集合。



文章来源: Why does removing the _first_ element of a list invalidate `.rend()`?