很久没写了……赶紧继续上
这里说右值,有一种解释是说位于赋值运算符左边的是左值,右边的是右值。其实,从“右值引用”这里看的话,一种更准确的定义是,不能放在运算符左边的叫做右值,其他的叫做左值。
好,说完右值,右值引用就好理解了,也就是对于右值的引用。那么,为什么之前没有右值引用呢?是因为右值主要都是一些临时变量,对它们的引用是没有意义的,因为理论上我们没有临时变量的任何知识,它是不可用的。而c++11引入右值引用,则主要是与move语义结合使用。那么,move语义是有什么用呢?这里的move可以按照文件操作中的"copy"和"move"两种操作中的后者来理解。例如,有一个object,内部包含有有分配好的内存。如果我们要用一个函数来生成这样一个object并且将其赋值给另外一个object,例如class_t obj1 = create_obj(),那么这里create_obj()会产生一个临时变量,这个临时变量会以深拷贝的形式赋值给obj1.而这个临时变量则会被销毁,同时内部的内存被释放。很浪费的操作。而引入move语义后,这里可以是这样,create_obj()生成的临时变量内部的内存地址会传给obj1,然后这个临时变量被销毁而这部分内存不会释放。
右值引用的声明形式:T &&,例如,int function(int&& a){}. 需要注意的是,右值引用只能引用右值,不能引用左值。也就是说,不能引用可以放在赋值运算符左边的值。所有具名的变量一定是左值。
带有move constuctor(移动构造函数)的声明形式如下(摘自http://imcc.blogbus.com/logs/107446664.html,有修改)
class vector { vector(const vector&); // 拷贝构造函数 vector(vector&&); // 移动构造函数 vector& operator= (const vector&); // 拷贝赋值函数 vector& operator =(vector&&); // 移动赋值函数 };
关于移动构造函数,在http://blog.csdn.net/zwvista/article/details/5665566有一个很好的例子,这里不再复制粘贴了。简言之就是,在移动构造函数里面,你可以把被右值引用的那个变量的内部资源指针置空,而把当前object的指针指向它们。
那么,move语义什么时候触发呢?
1. 如果class_t本身拥有移动赋值函数,那么class_t obj1 = create_obj()会触发右值引用。也就是说,你把一个右值赋值给一个有移动构造函数的object.
2. 如果class_t本身拥有移动构造函数,那么class_t obj1(create_obj())会触发右值引用。
3. 可以使用std::move()函数。这个函数的功能是把一个左值转换成一个右值,从而触发右值引用。
最后,一个写的比较好的关于move语义的介绍,http://www.cprogramming.com/c++11/rvalue-references-and-move-semantics-in-c++11.html。有兴趣可以去看看。是英文的。But an rvalue reference is not, in fact, an rvalue. It's an lvalue 很有意思的一句话。
(在最后,我真的觉得这东西主要是为了提升STL性能的……)