为什么删除列表的_first_元素会使`.rend()`无效
Why does removing the _first_ element of a list invalidate `.rend()`?
使用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
}
这是因为反向迭代器的引用逻辑与常规迭代器略有不同:它指向一个元素,但当取消引用时,它会产生对前一个元素的引用。
如果你尝试以下操作,你会很容易看到这一点:
#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
这不仅适用于列表,而且适用于所有提供双向迭代器的集合。
相关文章:
- Openssl 1.1.1d无效使用不完整的类型"struct dsa_st"
- 无法访问嵌套类.类的使用无效
- 如果用户输入无效,如何使用字符串变量-C++重复输入命令
- 如何解决错误:SCIP C++中的 SCIP 阶段无效 <10>
- 在没有参数列表的情况下使用模板名称"Event"无效,模板问题
- FFMPEG配置文件级别id大小无效
- 错误:从"int"到枚举c++的转换无效
- 如何修复此错误:className::className的无效使用
- 为什么将值返回函数传递给重载=运算符对运算符函数有效,而对其他运算符无效
- C++-模板嵌套类的引用初始化无效
- 错误:无效的预处理指令 #i 的意思是 #if?
- 多维数组 C++ 中数组下标的类型"int[int]"无效
- 在 C++ 中使用正则表达式错误时出现问题 括号表达式中的范围无效
- 从 'int' 到 'int*' CPP 的转换无效
- 如何接受 [ENTER] 键作为无效输入并发送错误消息
- 由于无效的 ValidateRgn() 子窗口不会收到WM_PAINT消息
- C++ PTHREADS - 无效转换无效*(*)()到无效*(*)(无效*)
- 声明为无效的变量或字段'...' Ardunio 编译器上的错误
- 数组下标的类型"float*[float]"无效
- 为什么删除列表的_first_元素会使`.rend()`无效