【发布时间】:2016-09-13 19:50:02
【问题描述】:
给出下面的代码(假设它被命名为deque.cpp)
#include <cstdio>
#include <deque>
int main()
{
std::deque<int> d = {1, 2, 3};
for (auto it = d.rbegin(); it != d.rend();) {
printf("it: %d\n", *it);
++it;
d.pop_back();
}
return 0;
}
用g++ -std=c++11 -o deque deque.cpp编译,运行良好:
$ ./deque
it: 3
it: 2
it: 1
但如果用-D_GLIBCXX_DEBUG(g++ -std=c++11 -o deque_debug deque.cpp -D_GLIBCXX_DEBUG编译,则会出现以下错误:
$ ./deque_debug
it: 3
/usr/include/c++/4.8/debug/safe_iterator.h:171:error: attempt to copy-
construct an iterator from a singular iterator.
...
看起来第二个循环的++it 是从单个迭代器构造的。
但我认为在第一个循环的++it 之后,迭代器指向2,pop_back() 不应使其无效。那为什么会出现错误呢?
注意:我知道代码可以重写如下:
while (!d.empty()) {
auto it = d.rbegin();
printf("it: %d\n", *it);
d.pop_back();
}
错误就会消失。
但我确实想知道错误代码到底发生了什么。 (这是否意味着反向迭代器实际上并不指向我期望的节点,而是指向它之后的节点?)
更新: @Barry 的回答解决了这个问题。 请让我提出一个额外的相关问题:代码
for (auto it = d.rbegin(); it != d.rend();) {
printf("it: %d\n", *it);
d.pop_back();
++it; // <== moved below pop_back()
}
应该是错误的,++it 应该在一个无效的迭代器上运行。但是为什么代码不会报错呢?
【问题讨论】:
-
这是否意味着反向迭代器实际上并不指向我期望的节点,而是指向它之后的节点? 是的!
-
如果有人来到这里想知道“
singular iterator到底是什么,我为什么要害怕引用它”:我在 IRC 上被推荐为 this link。 C++ 标准似乎将“奇异”值称为无效值。 “单数迭代器”仅仅意味着它指向 la-la land,无论出于何种原因(无论它是从一开始就未初始化,还是被erase()操作无效) .
标签: c++ c++11 iterator reverse-iterator