bob*_*obo 10 c++ stdlist reverse-iterator
使用XCode 4.6在Mac OS X上测试.
此示例代码显示std::list正如我所期望的那样删除工作的最后一个元素:迭代器引用list::end()仍然是"1结束"并且仍然有效,即使删除了最后一个元素.
但第二个例子反驳了我的直觉.删除列表的第一个元素会发生变化list::rend(),我认为这是"从头开始".
我的期望是错的吗?为什么这是错的?为什么通过删除最后一个元素引用"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
}
Run Code Online (Sandbox Code Playgroud)
And*_*owl 21
这是因为反向迭代器的引用逻辑与常规迭代器略有不同:它指向一个元素,但是当取消引用时,它会产生对前一个元素的引用.
如果您尝试以下操作,您将很容易看到:
#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;
}
Run Code Online (Sandbox Code Playgroud)
输出应该是:
3
2
Run Code Online (Sandbox Code Playgroud)
当反向迭代器物理上指向某个元素时,它逻辑上指向它之前的元素.因此,反向迭代器在物理上指向具有索引的集合中的元素i,当取消引用时,会生成(引用)具有索引的元素i-1:
i, *i
|
- 1 2 3 4 5 6 -
| |
*ri ri
Run Code Online (Sandbox Code Playgroud)
这就是为什么迭代器返回rend()实际指向集合中的第一个元素而不是第一个元素之前的元素的原因.因此,删除第一个元素会使其无效.
begin, *begin end, *end
| |
- 1 2 3 4 5 6 -
| | | |
*rend rend *rbegin rbegin
Run Code Online (Sandbox Code Playgroud)
这不仅适用于列表,而是适用于提供双向迭代器的所有集合.