返回对内部对象的引用时的常量

Const-ness when returning reference to an internal object

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

我正在努力理解下面的情况,它的行为与我预期的不同。

给定以下代码示例:

class ConstTestClass
{
    std::deque<unsigned long long> deque;
public:
    const std::deque<unsigned long long int> &getDeque() const{return deque;}
};
int main()
{
    ConstTestClass constTestClass;
    auto constDeque = constTestClass.getDeque();
    constDeque.emplace_back(1ULL);
}

我希望调用constDeque.emplace_back(1ULL);失败,因为我希望constDeque是对const std::deque<>的引用,但它实际上在GCC 5.4.0上编译时没有任何错误。

如果我将上面的行更改为const auto constDeque = constTestClass.getDeque();,它将无法按预期编译,因为constDeque现在是预期的类型。

我试图理解为什么auto可以从返回类型中删除常量,以及我理解中的错误所在。

编辑:这不是重复回答。我仍在寻找一种方法来确保调用方始终获得指向内部对象的常量引用(或指针),这样调用方将看到itnernal对象的状态更改,而无需修改它

auto使用与模板参数推导相同的规则。为了进一步澄清,假设您有一个函数(例如foo):

template<typename T>
void foo(T v) {
  v.emplace_back(1ULL);
}

然后你做以下操作:

std::deque<unsigned long long> dq;
const std::deque<unsigned long long> &dqr = dq;
foo(dqr);

此代码还将通过编译器Live Demo。之所以会发生这种情况,是因为根据模板参数推导规则,T将被推导为std::deque<unsigned long long>dqr将通过副本传递给foo

现在假设auto是一个模板参数(例如.T):

T constDeque = constTestClass.getDeque();

由于auto使用了与模板参数推导相同的规则,如foo中的示例所示,它将在std::deque<unsigned long long>中推导T

因此,您正在创建const成员std::deque成员变量的副本。为了得到你预期的行为,你必须对你的auto推导提供一点帮助,并写下:

auto &constDeque = constTestClass.getDeque();

或者,如果您想进一步向代码的读者澄清所得到的auto推导是const限定变量,您可以显式添加const限定符作为:

auto const &constDeque = constTestClass.getDeque();