对非Const对象的常量引用

时间:2017-07-02 00:23:52

标签: c++ reference

发现很难理解为什么我不能对可变对象进行不可变引用?如果我将引用传递给像这样的容器:

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有一定的统一性。

1 个答案:

答案 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之后无法确保其常量,您可能会也可能不会使用它来改变内容。