对非常量对象的常量引用

Constant Reference to Non-Const Object

本文关键字:常量 引用 对象 非常      更新时间:2023-10-16

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

auto f(const map<int, int>& x) -> decltype(non-const map iterator) {...}

它认为x是常量,我请求它的任何迭代器都是const_iterator类型。

我想要以下内容(或者我是这么认为的(:
auto f(map<int, int>& const x) -> decltype(non-const map iterator)
但它不编译。

这并不难解决,但我希望我的项目代码库在 const 方面有一些统一性。

长话短说,您无法以任何可靠的方式从conststd 容器中获取iterator

为了说明为什么会这样,请看一下容器是如何实现的。

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;

但是,由于容器在概念上是指针,而指针指向的内容因此在使用const限定时返回iterator在语义上是错误的。为了解决这个问题,我们引入了const过载,保证const容器真正const

map而言,发出iterator会立即破坏const应该承受的合同。map在发出iterator后无法确保其恒定性,您可能会也可能不会用它改变内容。