迭代std :: shared_ptr的std :: vector中的最后一个元素会导致分段错误

时间:2019-05-03 09:41:51

标签: c++ vector shared-ptr

请尝试编译并运行以下代码。 遍历共享指针的向量时,我必须删除最后一个元素,这将导致分段错误,但是我不明白为什么for到达el_it时迭代不会中断{1}},我必须手动执行(注释代码)。

v.end()

2 个答案:

答案 0 :(得分:1)

更改:

v.erase(el_it);

收件人

el_it = v.erase(el_it); // don't do this yet, read below

擦除会使迭代器无效。擦除的返回值是下一个元素的有效迭代器。因此,根据我上面的内容,您将跳过一个元素。我建议这样做:

for (auto el_it = v.begin(); el_it != v.end();) {
    auto el = *el_it;
    if (el->age_ == 2) {
        el_it = v.erase(el_it);
    } else {
        ++ el_it;
    }
}

答案 1 :(得分:1)

调用std::vector::erase()使您的el_it迭代器无效。您没有考虑到这一点。 erase()将新的迭代器返回到已删除元素之后的元素。您需要使用新的迭代器来继续循环。

尝试以下方法:

for (auto el_it = v.begin(); el_it != v.end();) {
    auto el = *el_it;
    if (el->age_ == 2) {
        el_it = v.erase(el_it);
    } else {
        ++el_it;
    }
}

或者,更好的选择是通过erase-remove idiom算法使用std::remove_if(),而不是完全手动循环:

v.erase(
    std::remove_if(v.begin, v.end(),
        [](auto el){ return (el->age_ == 2); } 
    ),
    v.end()
);

C ++ 20添加std::erase_if()使其更容易:

std::erase_if(v,
    [](auto el){ return (el->age_ == 2); } 
);