使用iterator和const_iterator调用erase

OMG*_*OMG 22 c++ data-structures

为什么调用erase容器的成员函数const_iterator失败?

它适用于非const iterator.

Unc*_*ens 29

这不会编译因为container::iterator并且container::const_iterator是两个不同的类型,并且擦除的唯一(单参数)版本是:iterator erase(iterator);

不接受a const_iterator可以被视为语言标准中的缺陷:http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2350.pdf

这种限制没有特别的原因.迭代器仅用于指示位置在(修改)的容器中,和既不在的情况下,insert或者erase是经修饰的(在的情况下,迭代器的"指针对象" erase它只是概念性地熄灭存在的,这是做一个正常事对于const对象).

当前标准表示"迭代器常量和容器常量"之间的混淆(这里也有其他答案),并且在C++ 0x中似乎const_iterator可以接受erase.


作为一种解决方法,您可以有效地iterator从a 获取,const_iterator因为容器必须首先是可变的.

下面的函数只适用于随机访问迭代器,因为使用其他类型的迭代器执行此操作可能有点太慢.

#include <vector>

template <class Container>
typename Container::iterator to_mutable_iterator(Container& c, typename Container::const_iterator it)
{
    return c.begin() + (it - c.begin());
}

int main()
{
    int arr[] = {1, 5, 2, 5, 3, 4, 5, 1};
    std::vector<int> vec(arr, arr + sizeof(arr) / sizeof(*arr));
    for (std::vector<int>::const_iterator it = vec.begin(); it != vec.end(); ) {
        //if (*it = 5) {  //const_iterator prevents this error
        if (*it == 5) {
            it = vec.erase(to_mutable_iterator(vec, it));
        }
        else {
            ++it;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,重新构建代码可能会更好,因此您const_iterator首先不需要a .在这种情况下,最好使用该std::remove算法.如果在擦除之前需要进行更多非变异工作,可以将其提取到单独的方法中等.


Lin*_*Lin 5

我只想强调UncleBens,David Rodriguez和Ise Westeria发布的答案/评论的一般正确性.

无论当前(或以前)的C++ 11之前的编译器的行为如何,const_iterator(应该)的const正确性立即停止,因为它在语义上等于const T*(或T*const) - 注意T本身可能是一个自己的const类型! - 因此它有效地防止代码修改容器中引用的对象.

但是,因为在C++中"删除"一个const指针是完全合法的(尝试它,它可以工作!),它应该是(并且行为已在C++ 11中得到纠正)合法以及"擦除"一个const来自容器的迭代器,只要容器本身不是const.

似乎Visual Studio 2010已经通过"擦除"接受const_iterator来正确运行,这当然让我有些头疼来追踪其他一些错误,这导致我发表这篇文章,最终澄清了"erase const_iterator"const的正确行为正确性.


Mah*_*esh 1

类型const_iterator不能用于修改元素或容器的值。

  • 有趣的是,至少在 C++0x 的 N3092 中,容器的擦除和插入方法确实采用了 `const_iterator` - 没有什么特别的原因为什么不适合这些方法,除了可能的 `const_cast` 黑客行为。需要实施它们。只要容器是可修改的,我就不会修改引用的项,我*只是*使迭代器无效(这种情况总是在 `const_iterator` 中发生)。 (5认同)
  • 删除与 C++ 中的修改不同。 (2认同)