std::advance在std::list末尾的行为异常问题咨询
关于std::list迭代器越界行为的疑问解答
首先看你提供的代码:
#include <iostream> #include <list> using namespace std; int main() { list<int> A; A.push_back(1); A.push_back(2); A.push_back(3); auto it = A.begin(); cout << *it << ' '; advance(it, 1); cout << *it << ' '; advance(it, 1); cout << *it << ' '; advance(it, 1); cout << *it << ' '; advance(it, 1); cout << *it << ' '; }
针对你提出的两个疑问,解答如下:
疑问1:迭代器前进到end()后解引用为何输出3?
当迭代器指向最后一个元素(值为3的节点)时,再执行advance(it, 1),迭代器会变成A.end()——这个迭代器本身不指向任何有效元素,是一个“尾后标记”。此时对end()迭代器进行解引用(*it)属于未定义行为,C++标准没有规定这种操作的结果。你看到输出3只是巧合:内存中end()指向的位置恰好保留了之前的3,但换个编译器、换个运行环境,这里可能输出乱码、直接崩溃,或者其他随机值,完全没有确定性。疑问2:最后输出的1是如何产生的?
在迭代器已经是end()的基础上,再执行advance(it, 1),属于进一步的越界操作,同样是未定义行为。此时迭代器已经完全超出了std::list容器管理的内存范围,访问的是容器之外的未知内存区域,输出的1只是该内存位置恰好存在的值,和std::list是不是循环队列没有任何关系——这种结果完全不可预测,不能当作规律。
总结:C++中,任何解引用end()迭代器、或让迭代器超出容器合法范围(小于begin()或大于end())的操作都是未定义行为,程序的输出或行为没有任何保证,绝对不能依赖这种现象编写代码。
内容的提问来源于stack exchange,提问作者Hee Hwang
相关产品推荐
相关产品推荐

