发现很难理解为什么我不能对可变对象进行不可变引用?如果我将引用传递给像这样的容器:
auto f(const map<int, int>& x) -> decltype(non-const map iterator) {...}
它认为x
是const,我请求它的任何迭代器都是const_iterator
类型。
我想要以下(或者我认为):
auto f(map<int, int>& const x) -> decltype(non-const map iterator)
但它没有编译。
这不会很难解决,但我希望我的项目代码基于const有一定的统一性。
答案 0 :(得分:0)
长话短说,你不能以任何可靠的方式从iterator
标准容器中获取const
。
为了说明原因,请看一下容器的实现方式。
template<typename T>
class map
{
struct node {
T data;
node *lchild, *rchild, *parent;
};
public:
iterator begin();
const_iterator begin() const;
private:
node* head;
};
容器由于其性质,需要以间接方式处理常量。它们通常包含一个指向存放对象的内存的指针,限定具有const
的容器只会影响指针及其方法。
// const map looks like
node* const head;
如果容器天真地返回iterator
,即使它被const
限定,编译器也不会抱怨,毕竟你没有语法上突变容器中的任何内容。
// this is legal but wrong in a const map
head->data = T{};
// constness only prevents this
head = nullptr;
但是,由于容器在概念上是指针和指针指向的东西,因此在使用iterator
限定时返回const
在语义上是错误的。为了解决这个问题,我们引入const
重载,确保const
容器真正成为const
。
就map
而言,发出iterator
会立即违反const
应承担的合同。 map
在发出iterator
之后无法确保其常量,您可能会也可能不会使用它来改变内容。