C++ 左值,左值引用,右值,右值引用

参考:

http://www.cnblogs.com/qicosmos/p/4283455.html

简述:

左值长什么样?

1
int i = 0; //i为左值,0为右值

按照官方的说法,如果一个变量有名字,就是左值,否则是右值。

定义两个函数

1
2
3
4
5
6
7
int GetVar(){
return 5; //返回右值
}
int& GetRefVar(){
int x=5;
return x; //返回左值(可以取地址操作,即你是没有办法这么定义的int& = 5;)
}

通常也可以认为,能取到地址的,就是左值。

在C++中T& 指向的是 lvalue,而 const T& 指向的,却可能是 lvalue 或 rvalue,所以在定义构造函数的时候,如果不定义移动构造函数,那自然就跑进T(const T& t)拷贝构造函数里面了。

1
2
3
4
5
6
int b = 100;
A a = b; //就是值的copy
A& a = b;//左值引用绑定,就是初始化一个引用。
A& a = GetRefVar();//左值引用绑定,就是初始化一个引用。GetRefVar()返回的是一个左值。
A&& a = GetVar(); //GetVar()返回的是一个右值,右值不能取到地址,但是可以通过A&&进行右值引用绑定,延长了GetVar()的生命周期,减少了GetVar()的析构和A的构造,换句话说GetVar()直接搬过来用了。但是和std::move()不同,move的必须是一个左值。
const A& a = GetVar();//或者使用const修饰,起到右值引用的作用。对引用求地址,就是对目标变量求地址。即引用名是目标变量名的一个别名。引用在定义上是说引用不占据任何内存空间,但是编译器在一般将其实现为const指针,即指向位置不可变的指针,所以引用实际上与一般指针同样占用内存。

如下,此时重载了=操作符函数,用const修饰,强调other不能被修改。

1
Vector3& operator=(const Vector3& other);

关于左值,右值以及语义转发的参考:
http://www.cnblogs.com/catch/p/3507883.html

完美转发

所谓完美转发,就是你传进来的参数是左值,那么我就按左值处理;你传进来的是右值,那么我就按右值处理。

1
2
3
在模板中T&&代表着转发引用
T&& -> 如果T = int&&(右值) -> int&& && -> int&&
T&& -> 如果T = int& (左值)-> int& && -> int&