----------------------------右值引用---------------------------------
右值定义:
通俗来讲,赋值号左边的就是左值,赋值号右边的就是右值。可以取地址是左值,不可以取地址的是右值。C++11,之前没有明确提出右值的概念,所以 C++11 以前这些说活都是正确的。
C++11 中的左值,仍然等同于 C++98 左值。C++11 中的右值,除了 C++98 中的右值以外,增加了将亡值的概念。
如下图
#include <iostream>
using namespace std;
int main(int argc, char *argv[])
{
int a; int & lref = a;
//int && rref = a; //!error:右值引用不能接受左值
//int & elref = a*34; //!error:普通引用不能接受临时值
const int &eclref = a*34;
int && erref = a*34;
return 0;
}
const T & 万能常引用
其本质也是产生了临时对象, 并且该临时对象是 const 的。 此对于非基本数据类型也适用, 但需要转化构造函数。
class A
{
public:
A(){
cout<<"A() "<<this<<endl;
}
~A(){
cout<<"~A() "<<this<<endl;
}
A(const A &another)
{
cout<<"A(const A&)"<<&another<<"->"<<this<<endl;
}
void dis()
{
cout<<"xxxxoooooooooooo"<<endl;
}
};
A getObjectA()
{
return A();
}
int main(int argc, char *argv[])
{
// int& ri = 5;
// const & cri = 5;
// float f = 34.5;
// int & irf = f;
// const int & cirf = f;
// A objA;
// int& irA = objA;
// const int& cirA = objA;
// cout<<cirA<<endl;
const A& ret = getObjectA();
ret.dis(); //!error:一个const对象,没有const函数,不能再完成调用。
return 0;
}
此种举措,也可以在返回中避免临时对象,再次拷贝和销毁。但时临时对象的性质是 const 的,也会给后续的使用带来不便。
右值引用与左值引用的对比
1) 都属于引用类型。
2)都必须初始化。 左值引用是具名变量值的别名, 右值引用是匿名变量的别名。
3) 左值引用, 用于传参, 好处在于, 扩展对象的作用域。 则右值引用的作用就在于延长了临时对象的生命周期。
4) 避免“先拷贝再废弃” 带来的性能浪费。
5) 对将亡值进行引用的类型; 它存在的目的就是为了实现移动语义
const T & 与T && 本质对比
#include <iostream> using namespace std; int main( ) { const int & i =10;
int && iii = 10 }
/*int && iii = 10的汇编代码
0x08048400 mov $0xa,%eax 0x08048405 mov %eax,-0xc(%ebp) 0x08048408 lea -0xc(%ebp),%eax 0x0804840b mov %eax,-0x4(%ebp)
第一句将10赋值给eax,第二句将eax放入-0xc(%ebp)处,“临时变量会引用关联到右值时,右值被存储到特定位置”,-0xc(%ebp)便是该临时变量的地址,后两句通过eax将该地址存到iii处。
通过上述代码,我们还可以发现,在上述的程序中-0x4(%ebp)存放着右值引用iii,-0x8(%ebp)存放着左值引用,-0xc(%ebp)存放着10,而-0x10(%ebp)存放着1,左值引用和右值引用同int一样是四个字节(因为都是地址)
const int & i =10的汇编代码
0x08048583 mov $0xa,%eax 0x08048588 mov %eax,-0x8(%ebp) 0x0804858b lea -0x8(%ebp),%eax 0x0804858e mov %eax,-0x4(%ebp)
-0x4(%ebp)处存放着i,-0x8(%ebp)处则存放着临时对象10,程序将10的地址存放到了i处。看到这里会发现const引用在绑定右值时和右值引用并没有什么区别。
*/
参考:https://www.cnblogs.com/likaiming/p/9045642.html
重要的事情再说一遍:
总之读完该篇博文你只需要知道:右值引用存在的意义就在于它既获得了同const T&同样的效率,又解决了const引用不可作为non-const类型使用的问题!
想要更深入的了解右值引用以及他的作用:请参考另一篇博文:https://www.cnblogs.com/wangkeqin/p/9338358.html