在C ++ 11中,可以使用可变rvalue引用初始化const lvalue引用。然后,rvalue引用的值可以改变,从而产生可见的突变,即const lvalue指的是什么。这是一个例子:
int && rval = 3;
const int & lval = rval;
cout << "lval = " << lval << endl;
cout << "rval = " << rval << endl;
rval ++;
cout << "lval = " << lval << endl;
输出(来自clang 3.2和gcc 4.8.2,两者都是-std = c ++ 11):
lval = 3
rval = 3
lval = 4
我会猜测这是因为无法通过左值引用修改到引用,但可以通过右值引用修改它。但是,我不明白为什么允许const左值引用可变对象。
有人可以解释这个的基本原理,并提供处理这种情况的最佳实践。还有,还有其他类似的例子可以破坏常量吗?
答案 0 :(得分:14)
但是,我不明白为什么允许const左值引用可变对象
对某些内容进行const
引用只意味着您无法通过该引用修改该对象。这并不意味着没有人被允许改变对象。
假设你有一个功能:
void f(Foo const& bar);
该函数向调用者声明它不会修改bar
。而已。没有什么比这更好的了。它没有说明bar
执行时f
发生了什么(例如在另一个线程中);语言没有办法表达那样的约束。
最后一点:
int && rval = 3;
rval
是左值。它有一个名称,可以在作业的左侧,正如您的代码清楚地表明的那样。右值引用和左值引用之间的区别在于右值引用可以绑定到rvalues - 而不是它们本身就是rvalues。
这就是给出类似
的原因void foo(unique_ptr<X>&& x)
{
aVector.emplace_back(x);
}
无法编译。 x
被声明为右值引用,但在foo
内,它有一个名称,可以在赋值的左侧,并且是左值。将其移至其他内容需要使用move
或类似内容:
void foo(unique_ptr<X>&& x)
{
aVector.emplace_back(move(x)); // Ok
}