理解 std::vector::erase() 中的迭代器失效
在本次讨论中,我们深入研究迭代器失效的主题:调用 std::vector::erase()。从之前的争论中可知,从向量中删除元素会使位于被删除元素之后的迭代器无效。然而,出现了一个问题:位于被擦除元素处的迭代器是否仍然被认为有效?
尽管我们直观地理解位于被擦除位置的迭代器应该保持可用,但精确的行为并不总是清晰的。为了说明这个概念,让我们分析以下从向量中删除所有奇数整数的代码片段:
<code class="cpp">typedef std::vector<int> vectype; vectype vec; for (int i = 0; i < 100; ++i) vec.push_back(i); vectype::iterator it = vec.begin(); while (it != vec.end()) { if (*it % 2 == 1) vec.erase(it); else ++it; }</code>
虽然此代码成功执行,但它违反了最佳实践。根据 C 标准,erase() 会使作为参数提供的迭代器处或之后的所有迭代器无效。在这种情况下,这意味着被擦除位置的迭代器变得无效。
但是,erase() 可以方便地返回一个新的迭代器,该迭代器指向紧随被擦除元素之后的元素,或者指向 vec.end () 如果不存在这样的元素。这个新的迭代器可以用来安全地恢复迭代。
需要注意的是,上述删除奇数元素的方法效率不高。每次删除一个元素时,后续元素都必须在向量中向左移动,从而导致复杂度为 O(n2)。使用擦除-删除惯用法可以更有效地完成此任务,该惯用法的运行时间为 O(n)。通过创建像 is_odd() 这样的谓词,我们可以优化擦除操作:
<code class="cpp">bool is_odd(int x) { return (x % 2) == 1; } vec.erase(std::remove_if(vec.begin(), vec.end(), is_odd), vec.end());</code>
以上是## std::vector::erase() 中擦除位置处的迭代器仍然有效吗?的详细内容。更多信息请关注PHP中文网其他相关文章!