为什么在 C++11 中允许通过 const_iterator 擦除?

Why is erasing via a const_iterator allowed in C++11?

从 GCC 4.9.2 开始,现在可以编译通过 const_iterator.

插入或删除容器元素的 C++11 代码

我明白插入接受 const_iterator 有何意义,但我正在努力理解为什么允许通过 const_iterator 进行擦除是有意义的。

这个问题已经 discussed previously,但我还没有看到对行为变化背后的基本原理的解释。

我能想到的最佳答案是更改的目的是使 const_iterator 的行为类似于 const T*.

显然,允许使用 const T* 删除的一个主要原因是启用如下声明:

const T* x = new T;
....
delete x;

但是,它也允许以下不太理想的行为:

int** x = new int*[2];
x[0] = new int[2];
const int* y = x[0];
delete[] y; // deletes x[0] via a pointer-to-const

我正在努力了解为什么 const_iterator 模仿这种行为是一件好事。

eraseinsert 是集合的非 const 成员函数。非常量成员函数是公开变异操作的正确方法。

参数的常量无关紧要;他们没有被用来修改任何东西。可以修改集合,因为集合是非const(保存在隐藏的this参数中)。

比较:

template <typename T>
std::vector<T>::iterator std::vector<T>::erase( std::vector<T>::const_iterator pos );
                                                                ^^^^^ ok

不允许的类似重载

template <typename T>
std::vector<T>::iterator std::vector<T>::erase( std::vector<T>::iterator pos ) const;
                                                                         wrong ^^^^^
  1. 这里的第一个问题是迭代器的常量是否应该暗示整个容器的常量或者只是被迭代的元素的常量。

    显然,后者是正确的方法。迭代器的常量并不意味着容器的常量,它只意味着容器元素的常量。

  2. 自古以来,构造一个物体及其对称对应物-破坏一个物体-被认为是关于对象本身的元操作。对于这些操作,该对象一直被认为是可变的,即使它被声明为 const。这就是您可以在其构造函数和析构函数中合法修改 const 对象的原因。这就是您可以通过 const T * 指针 delete 类型 T 的对象的原因。

鉴于 1 所指的解决方案,很明显 2 也应该扩展到迭代器。