我试图理解以下情况,其行为与我的预期不同。
给出以下代码示例:
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对象的状态更改,而无法对其进行修改。
答案 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