先来一个一个简单定义:
左值(locator value或left value)代表一个在内存中占有确定位置的对象(换句话说就是有一个地址可以找到)。
右值通过排他性来定义,每个表达式不是左值就是右值。因此从上面的左值的定义,右值是在不在内存中占有确定位置的表达式,(并不是没有地址,只是我们找不到)。
常量,函数返回的值等都是右值;而非匿名对象(包括变量),函数返回的引用,const对象等都是左值。
1.//左值引用
int a=10;
int &a1=a;//正确,a为左值类型,因为可以我们找到他的地址
int &a=10;//错误,左值引用不能引用一个右值类型的常量,(10是常量,常量为右值)
const int &a=10;//正确,因为加上const之后就为右值类型延长了消亡的时间,使其可以存活到main函数结束前。当一个右值被 const 引用指向时,它的生命周期就被延长了
1,2对比着看
2.//右值引用
int &&a=10;//正确,右值引用一个右值类型
int var = 10;
int&& var1 = var;//错误,因为无法将右值引用绑定到左值上,右值引用右边得是右值,而这里的var显然是个可以找到地址的左值
//右值引用绝对不能引用左值类型的,加上const也不行,这点是和左值引用不同的地方
const int&&var1=var//照样报错,加上const也不行,这从基本原理上就不对,左值和右值的关系并不是简单的对等的。
3.//非引用返回的函数返回的都是右值,引用返回的函数返回的是左值
int fun() { }
int main()
{
int& z = fun();//左值引用,报错
const int& z1 = fun();//正确
int&& z2 = fun();//正确
}
3,4对比着看
int &fun() { }
int main()
{
int& z = fun();//左值引用,正确
const int& z1 = fun();//延长生命期的左值引用,正确
int&& z2 = fun();//报错,右值引用不能绑定左值
const int&& z2 = fun();//报错,加const也不行,还在这疑惑的都是原理没弄明白
}
在C++之中,使用左值去初始化对象或为对象赋值时,会调用拷贝构造函数或赋值构造函数。而使用一个右值来初始化或赋值时,会调用移动构造函数或移动赋值运算符来移动资源,从而避免拷贝,提高效率。 而将亡值可以理解为通过移动构造其他变量内存空间的方式获取到的值。在确保其他变量不再被使用、或即将被销毁时,来延长变量值的生命期。而实际上该右值会马上被销毁,所以称之为:将亡值