2

我有这段代码:

for (std::vector<Marker>::iterator it = markers.begin(); it != markers.end(); ++it) {
    if (it->getDots().size() < 3) {
        markers.erase(it);
    }
}

在其中一个测试输入(应用程序进行图像分析)中,我得到了一个段错误。我试图调试代码(无济于事)并注意到一件事。当要求 gdbp markers.size()我收到$9 = 3. 所以我希望循环迭代 3 次,但令人惊讶的是它(至少)做了 5 次。在第五次迭代中有一个段错误。我还注意到,导致错误的不是*it(here ) 的取消引用。it->具体来说it->getDots(),这是一个简单的吸气剂。

我很少用 C++ 编写,所以这可能是一些简单的错误,但我的调试和谷歌搜索都没有带来任何解决方案。你能帮忙吗?

我想强调的是,在各种不同的输入(略有不同的图像)上,此功能可以正常工作,因此我更难以追踪错误。

4

3 回答 3

6

vector::erase使所有指向被擦除元素的迭代器以及所有后续元素无效。所以it变得无效,并且++it下一次循环迭代的表达式表现出未定义的行为。

编写此逻辑的最佳方法是使用erase-remove idiom

于 2013-08-10T18:28:24.457 回答
3

问题是这一行:

markers.erase(it);

迭代器无效。但这没关系,erase返回一个有效的迭代器:

auto it = markers.begin();
while(it != markers.end())
{
    if(it->getDots().size() < 3) {
        it = markers.erase(it);
    }
    else ++it;
}
于 2013-08-10T18:27:57.293 回答
2

it擦除时需要更新:

it = markers.erase(it);

因为erase将“更改” vector,并且您的当前it不再有效(只有it++当您没有删除它时才会这样做)。

但是,更常见的方法是使用这种类型的构造:

markers.erase(std::remove(markers.begin(), markers.end(), number_in), markers.end());
于 2013-08-10T18:26:55.003 回答