为什么删除列表的_first_元素无效`.rend()`? [英] Why does removing the _first_ element of a list invalidate `.rend()`?

查看:132
本文介绍了为什么删除列表的_first_元素无效`.rend()`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

Tested on Mac OS X using XCode 4.6.

此示例代码显示删除 std :: list 按我的预期工作: list :: end()的迭代器引用仍然是1 over the end,仍然有效,

This example code shows removing the last element of an std::list works as I expected: an iterator reference to list::end() is still "1 past the end" and is still valid, even through removal of the last element.

但是第二个例子反映了我的直觉。移除列表中的第一个元素更改 list :: rend() 开始。

But the second example counters my intuition. Removing the first element of the list changes list::rend(), which I thought was "1 past the beginning".

我的期望错了吗?为什么会出错?为什么你通过删除最后一个元素引用1过去结束仍然有效(不应该?),但是引用开头之前的1( .rend())在删除前面的元素后变得无效?

Was my expectation wrong? Why was it wrong? Why does your reference to "1 past the end" through deletion of the last element remain valid (should it not?), but a reference to "1 in front of the beginning (.rend()) becomes invalid after removal of the front element?

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
}


推荐答案

这是因为反向迭代器与常规迭代器具有稍微不同的引用逻辑:它指向一个元素,但是当被取消引用时,它产生对前一个元素的引用。

This is due to the fact that a reverse iterator has a slightly different referencing logic than a regular iterator: it points to an element, but when dereferenced, it yields a reference to the previous element.

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

You will easily see this if you try the following:

#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 :

When a reverse iterator physically points to a certain element, it logically points to the element which precedes it. Thus, a reverse iterator physically pointing to the element in a collection with index i, when dereferenced, yields (a reference to) the element with index i-1:

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

这是为什么迭代器返回 rend()实际上指向集合中的第一个元素,而不是第一个元素之前的元素。因此,删除第一个元素会使其无效。

This is the reason why an iterator return by rend() actually points to the first element in a collection, and not to the one before the first element. Removing the first element, therefore, invalidates it.

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

这不仅适用于列表,集合,提供双向迭代器。

This does not apply only to lists, but to all collections which offer bidirectional iterators.

这篇关于为什么删除列表的_first_元素无效`.rend()`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆