5.左值与右值
移动是指将右值移动,因此,我们首先要知道什么是左值,什么是右值。
1.变量是左值
由于变量是左值,所以我们不能将一个右值引用绑定到左值上。参考以下例子:
int i=5;//左值
int& r=i;//左值引用
int&& o=i;//错误,i是左值
2.表达式是右值
由于表达式是右值,所以我们可以将一个右值引用绑定到左值上。参考以下例子:
int i=4;
int&& r=i*16;//这是右值!!!
注意:右值引用也是左值!!! 由于变量都是左值,所以右值引用也是左值!!!
以下代码是错误的!!!
int i=6;
int&& o=i*42;
int&& r=o;//错误,o是左值!!!
6.std::move函数
如5.2章所说,那么我们也就没有办法用一个右值引用去给另一个右值赋值,那么每次都要重新写一个表达式,这样非常麻烦。我们可以使用标准库std::move() 函数就可以简便许多。它定义在标准库utility中。所以上图可以这么改:
int i=9;
int&& p=i+68;
int&& q=std::move(p);
6.1移动构造函数
既然有可能使用右值引用,那么我们还要写一个移动构造函数。形式如下:
class A{
//...
public:
A(){ }
A(const A&);
A(A&& mem){ std::move(mem); }
//...
};
6.2std::move后…
当我们移动一个对象之后,这个对象就成了移后源对象。一个移后源对象必须是可析构的。所以,我们要将移动后的对象进入可析构状态。
举个例子,假设我们的pointer类有一个指针,那么我们应该这么写它的移动构造函数:
class pointer{
//...
private:
char* point;
//....
public:
//...
pointer(pointer&& mem):point(nullptr){ std::move(mem); }
//正确,析构point是安全的
//...
};
移动对象后,我们只能对它赋值或析构
如有错误,请在评论区提出,谢谢!