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

时间:2019-06-19 06:00:17

标签: c++ list debugging iterator

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

第一个代码:

#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);
    }
}

第二个代码:

#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--);
    }
}

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

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

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

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

有人可以建议我这些代码示例为何表现不同吗?

1 个答案:

答案 0 :(得分:5)

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

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