新版的C++标准库出现了很多C++11的新特性,刚开始接触确实很费劲,特别是右值引用和move函数这种基于效率的考虑损失了语言的简单直接的特性,废话不多说,先看右值引用。
C++中根据const和non_const,lvalue和rvalue可分为四类对象
non_const const
lvalue 非常量左值 常量左值
rvalue 非常量右值 常量左值
如果使用C++03标准,函数的参数选择const reference(常量引用),可以接受所有的传值类型:常量/非常量的左值/右值,即:
void f(const T& t);
可以接受所有T类型的对象传入。
而void f(T& t);
只能接受非常量的左值传入。
我们没有办法在函数参数类型区分只接受左值,或右值,要办到这件事,需要引入右值引用的概念。
void f(T&& t);
T&&不是引用的引用,是右值引用。C++11(准确的说是C++09)引入此项特性的目的是了健全左右值的引用。
为什么要区分?
考虑下面的函数,它已经被用烂了:
vector<int> f(vector<int>& p) { vector<int> a; for(int i = 0 ;i < 100; i++) a.push_back(p+i); return a; }vector<int> test = f(v);//v is a vector
这样的函数行为导致vector<int>a的初始化是一种浪费的行为,它创建了一段在堆上的空间存放数据,再把这些数据拷贝给vector<int> test。
我们完全可以把vector<int> a在堆上申请的空间以及被设置好的数据直接给test,告诉test你拿去用好了,反正我马上就死了。
好了,如果我们的vector中有一个构造函数,能够拿test的空间和数据,那么上面的过程也就完成了:
vector<int>(vector<int>&& v)//vector<int>的构造函数的重载版本 {//这是简化版的vector,只是为了让你看懂move的意义所在 ptr = v.ptr;//假设ptr是指向存储地址的指针 size = v.size;//size是vector中存储空间的大小 .... v.ptr = 0;//neccessary! }
注意到构造函数的参数是vector<int>&&,它只接受右值引用的传入。
为什么要只接受右值的引用?因为,我们只想要马上就销毁的对象才把数据move过来,而其他还要继续使用的对象,数据是拷贝过来的(通过其他的拷贝构造函数的重载版本实现)
同时,我们的f函数需要修改如下:
vector<int> f(vector<int>& p)//注意返回类型不是vector<int>&& { vector<int> a; for(int i = 0 ;i < 100; i++) a.push_back(p+i); return std::move(a); }
move的作用是把对象修改为一个右值的引用
好了,如果没有右值引用,我们就没法完成上述功能。
推荐一篇博文,讲得比较详细http://blog.csdn.net/pongba/article/details/1684519