返回对内部对象的引用时的约束

时间:2016-07-19 11:50:53

标签: c++ c++11 language-lawyer

我试图理解以下情况,其行为与我的预期不同。

给出以下代码示例:

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可以从返回类型中删除const-ness以及我理解中的错误所在。

编辑:这不是一个副本。我仍在寻找一种方法来确保调用者始终获得内部对象的const引用(或指针),因此调用者将看到对itnernal对象的状态更改,而无法对其进行修改。

1 个答案:

答案 0 :(得分:2)

@Query("{'MyData..fromDatestamp' : { $gte: { $numberLong: \"?0\" } }}") @Query("{'MyData..fromDatestamp' : { $gte: { $numberLong: '?0' } }}") 使用与template argument deduction相同的规则。为了进一步澄清它,假设您有一个函数(例如auto):

foo

然后执行以下操作:

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

此代码也将传递编译器Live Demo。发生这种情况是因为根据模板参数推断规则std::deque<unsigned long long> dq; const std::deque<unsigned long long> &dqr = dq; foo(dqr); 将推断为T,而std::deque<unsigned long long>将通过副本传递给dqr

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

T

由于T constDeque = constTestClass.getDeque(); 使用与模板参数扣除相同的规则(如auto中的示例所示),它将在foo中推断出T

因此,您正在创建std::deque<unsigned long long>成员const成员变量的副本。为了获得您期望的行为,您必须为std::deque扣除提供一点帮助并写下:

auto

或者,如果您想进一步向您的代码的读者澄清产生的auto &constDeque = constTestClass.getDeque(); 推论是auto限定变量,您可以明确地将const限定符添加为:

const