列表元素被删除时,迭代器结束时会发生什么?

问题描述:

我写了这个简单的测试程序。但我不明白这里会发生什么。因为在输出一件奇怪的事情:列表元素被删除时,迭代器结束时会发生什么?

std::list<std::pair<double,double>> l; 
l.push_back({0.3,0.9}); 
l.push_back({-0.3,0.5}); 
l.push_back({0.3,0.7}); 
l.push_back({1.2,1.83}); 


for(auto it=l.begin(); it!=l.end(); ++it){ 
    double lx= it->first + 0.01; 
    double ly= it->second + 0.01; 

    it->first = lx; 
    it->second = ly; 

    if(lx < 0.0 || lx > 1.0 || ly < 0.0 || ly > 1.0){ 
    it = l.erase(it); 
} 

如果我打印的清单,我得到:

0.32, 0.92 
0.31, 0.71 

为什么迭代器返回的第一个元素(两次+ 0.1)?

+1

if中的== 0是多余的,实际上整个if是无用的,因为'it!= end()'会处理这个问题。我不确定你为什么说第一个元素有两次?它看起来像你要删除位置1和3的元素,因此打印元素0和2. – Borgleader

+0

感谢您的答案。是的,它打印元素0和2,但它在第一个元素上加两次0.1。我不明白为什么:它应该是 (0.31,0.91)和(0.31,0.71) – Susliks

+0

就像旁边一样,这样做的典型模式是* erase-remove idiom * with l.erase(std: :remove_if(...),l.end())'。 – ArchbishopOfBanterbury

it=list.erase(it); 

这会删除元素it。然后在之后返回迭代器位置

当您的for循环完成迭代时,它会前进it,通过++然后检查它是否等于end()

所以你的循环都会在每次擦除后跳过元素。不好。如果它擦除最后一个元素,它就会通知最后一个迭代器,这是非法的。

for循环标题中删除++it。在循环的底部,提前itit处擦除,而不是两者都不是。

奇怪的打印行为是由于UB造成的。您在位置0处递增数据。您在位置1处递增数据,然后将其删除。您跳过位置2.您在位置3增加数据,然后删除它。您超前结束迭代器(未定义的行为)。然后发生随机事件,恰好会再次增加数据位置0和2。作为一个猜测,末端迭代器上的++恰好会循环回到特定情况下的第一个元素(这根本不能保证,但是UB会发生任何事情)。然后第二个循环正常运行,在两个元素处递增数据并删除任何内容。