使用迭代器与 const_iterator 调用擦除

2021-12-22 00:00:00 data-structures c++

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

Why does calling the erase member function of a container with a const_iterator fail?

它适用于非 const iterator.

It works with a non const iterator.

推荐答案

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

This doesn't compile because container::iterator and container::const_iterator are two distinct types and the only (one-argument) version of erase is: iterator erase(iterator);

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

Not accepting a const_iterator can be viewed as a defect in the language standard: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2350.pdf

此限制没有特别的原因.迭代器仅用于指示(可修改)容器中的位置,并且在inserterase的情况下都不是指针"修改过的迭代器(在 erase 的情况下,它只是在概念上不存在,这是 const 对象的正常做法).

There is no particular reason for this restriction. The iterator is only used to indicate a position in the (modifiable) container, and neither in case of insert or erase is the "pointee" of the iterator modified (in case of erase it just conceptually goes out of existence, which is a normal thing to do for const objects).

当前的标准表明迭代器常量和容器常量"之间存在混淆(就像这里的其他答案一样),而且在 C+ 中,const_iterator 似乎可以被 erase 接受+0x.

Current standard indicates a confusion between "iterator constness and container constness" (as do other answers here), and it seems const_iterator might become acceptable for erase in C++0x.

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

As a workaround, you can validly obtain an iterator from a const_iterator because the container has to be mutable in the first place.

下面的函数只能为随机访问迭代器编译,因为使用其他类型的迭代器可能有点太慢了.

The function below is only compilable for random access iterators, as it might be a bit too slow to do this with other types of iterators.

#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;
        }
    }
}

然而,最好重新构造代码,这样您就不需要 const_iterator .在这种情况下,最好使用 std::remove 算法.如果你需要在擦除之前做更多的非变异工作,你可以将它提取到一个单独的方法中,等等.

However, it might be better to restructure code so that you don't need a const_iterator in the first place. In this case, it would be better to use the std::remove algorithm. If you need to do more non-mutating work before erasing, you can extract that into a separate method etc.

相关文章