c++中引入了右值引用和移动语义,可以避免无谓的复制,提高程序性能。
-
C++中所有的值都必然属于左值、右值二者之一。
-
左值是指表达式结束后依然存在的持久化对象,右值是指表达式结束时就不再存在的临时对象。
-
所有的具名变量或者对象都是左值,而右值不具名。
-
区分左值和右值的便捷方法:看能不能对表达式取地址,如果能,则为左值,否则为右值。
-
书上将右值分为将亡值和纯右值。纯右值就是c++98标准中右值的概念,如非引用返回的函数返回的临时变量值;一些运算表达式,如1+2产生的临时变量;不跟对象关联的字面量值,如2,'c',true,"hello";这些值都不能够被取地址。
-
而将亡值则是c++11新增的和右值引用相关的表达式,这样的表达式通常时将要移动的对象、T&&函数返回值、std::move()函数的返回值等。
-
不懂将亡值和纯右值的区别其实没关系,统一看作右值即可,不影响使用。
int i=0; // i是左值,0是右值
class A {
public:
int a;
};
A getTemp() {
return A();
}
A a = getTemp(); // a是左值,getTemp()的返回值是右值(临时变量)
- c++98中的引用很常见,就是给变量取了个别名。
- 在c++11中,因为增加了右值引用(rvalue reference)的概念,所以c++98中的引用都称为了左值引用(lvalue reference)。
- c++11中的右值引用使用的符号是&&。
- 左值引用, 使用 T&, 只能绑定左值。
- 右值引用, 使用 T&&, 只能绑定右值。
- 常量左值引用, 使用 const T&, 既可以绑定左值又可以绑定右值。
- 已命名的右值引用,编译器会认为是个左值。
int a = 10;
int &refA = a; // refA是a的别名, 修改refA就是修改a, a是左值,所以是左值引用
// int &b = 1; // 编译错误! 1是右值,不能够使用左值引用
/*****************************************/
int&& a = 1; // a是右值引用,实质上就是将不具名(匿名)变量取了个别名
int b = 1;
// int&& c = b; // 编译错误! 不能使用右值引用绑定左值
class A {
public:
int a;
};
A getTemp()
{
return A();
}
A && a = getTemp(); // a是右值引用,getTemp()的返回值是右值(临时变量),a延长了右值临时变量的生命周期。