每次循环迭代后递减迭代器显示奇怪的行为

Lan*_*AOH 4 c++ debugging iterator list

我创建了一个程序来尝试对列表数据结构的语义进行练习。我注意到以下代码段有一个怪异的区别:

第一个代码:

#include<iostream>
#include<list>

using namespace std;

int main() {
    list<int> l;
    int n = 100;
    for(int i = 0; i < n; i++) {
        l.push_back(i);
    }
    list<int>::iterator it = l.end();
    it--;
    for(; !l.empty(); it--) {
        cout << "the size of l is " << (int) l.size() << endl;
        l.erase(it);
    }
}
Run Code Online (Sandbox Code Playgroud)

第二个代码:

#include<iostream>
#include<list>

using namespace std;

int main() {
    list<int> l;
    int n = 100;
    for(int i = 0; i < n; i++) {
        l.push_back(i);
    }
    list<int>::iterator it = l.end();
    it--;
    for(; !l.empty();) {
        cout << "the size of l is " << (int) l.size() << endl;
        l.erase(it--);
    }
}
Run Code Online (Sandbox Code Playgroud)

这两段代码的目标都很简单-只需擦除列表中的所有元素。

它们之间的唯一区别是列表迭代器递减的位置。在第一个代码示例中,我使用了for循环控制流来减少迭代器。在第二篇文章中,我使用了后减运算符来减少迭代器。

根据我的理解,上面的代码示例应该是等效的,因为在删除列表中的元素后,我会立即递减迭代器。此外,根据STL文档,仅列表中被删除元素的迭代器无效。因此,不应有任何未定义的行为。

问题是,第二个代码示例按预期方式工作-擦除列表中的所有元素后停止。但是,对于第一个样本,列表大小甚至可能变为负数!当我尝试增加列表中元素的初始数量时,第一个程序崩溃了一半。

有人可以就这些代码示例为何表现不同的问题向我提出建议吗?

son*_*yao 5

第一个代码具有未定义的行为。如您所说,erase使迭代器无效,之后的it--求值将导致UB。

第二个代码很好;请注意,评估顺序不同。it--将递减迭代器,然后返回原始值(这是后递减运算符的作用)。原始值将传递给erase以后。减少之前发生,erase所以很好。