左值和右值
什么是左值和右值?
按照我们常规理解左值就是在等号左边的值,右值是等号右边的值。如果你要这么理解,你就会发现遇到++i 或i++ 这一类的语句你就开始混乱了!
其实左值和右值是我们习惯性的叫法,他的全拼应该是: 左值是:locator value (可寻址的数据) 右值是:read value (不可寻址的数据或用来读的数据)
我们常规去理解,应该理解为: 在该程序语句之后能再找到该值,就是左值;否则就是右值。就是不可寻址!
举例说明
左值:
++x;
y*=33;
右值:
x++;
y+3;
123;
程序分析
#include<iostream>
#include<string>
#define func(x) _func(x,"func("#x")")
using namespace std;
void _func(int &x,string str){
cout << str << "left value !"<<endl;
return ;
}
void _func(int &&x,string str){
cout << str << "right value !"<<endl;
return ;
}
int main(){
int x = 3;
int y = 4;
func(123);
func(x++);
func(++x);
func(x*3);
func(x*=3);
func(y/4);
func(y/=4);
return 0;
}
输出结果为:
func(123)right value !
func(x++)right value !
func(++x)left value !
func(x*3)right value !
func(x*=3)left value !
func(y/4)right value !
func(y/=4)left value !
左值引用和右值引用
什么是左值引用和右值引用?
引用表示为符号“&”; 引用就是用另外的名称来索引到该变量。
左值引用
左值引用得到的就是还是一个左值。
#include<iostream>
using namespace std;
int main(){
int a = 10;
int &b = a;
cout << b << endl;
b = 5;
cout << a << endl;
cout << &a << " " << &b << endl;
return 0;
}
分析:
其中a和b都是左值,他们都是一个变量,且都是表示相同地址上存放的某个int类型的数。 且此时输出a和b的地址是一样的。
右值引用 (important!!!)
右值引用的使用常常在自定义类中,可以查看该博文去理解。
右值引用操作符为 “&&”; 右值引用得到的是一个左值。 右值引用通常将一个临时变量拿过来用。 右值引用最主要的功能是解决的是自定义类重复构造冗余的问题。
下面三种情况就告诉你什么时右值引用?为什么要有右值引用?
#include<iostream>
using namespace std;
class A{
int x;
public:
A(int x = 0):x(x){
cout << this << ":default constructor"<<endl;
}
A(const A&a):x(a.x){
cout << this << ":copy constructor"<<endl;
}
A operator+(const A& a){
return A(x+a.x);
}
~A(){
cout << this << ":destructor"<<endl;
}
};
int main(){
A a(1),b(3);
a+b;
cout << "====================="<<endl;
return 0;
}
通过关闭返回值优化g++ test2.cpp -fno-elide-constructor ,可以看到结果:
0x7fffbe1e127c:default constructor
0x7fffbe1e1280:default constructor
0x7fffbe1e1244:default constructor
0x7fffbe1e1284:copy constructor
0x7fffbe1e1244:destructor
0x7fffbe1e1284:destructor
=====================
0x7fffbe1e1280:destructor
0x7fffbe1e127c:destructor
int main(){
A a(1),b(3);
A c = a+b;
cout << "====================="<<endl;
return 0;
}
关闭返回值优化,得到结果:
0x7ffd08697558:default constructor
0x7ffd0869755c:default constructor
0x7ffd08697524:default constructor
0x7ffd08697564:copy constructor
0x7ffd08697524:destructor ~A(a.x+b.x)
0x7ffd08697560:copy constructor
0x7ffd08697564:destructor
=====================
0x7ffd08697560:destructor
0x7ffd0869755c:destructor
0x7ffd08697558:destructor
int main(){
A a(1),b(3);
A &&c = a+b;
cout << "====================="<<endl;
return 0;
}
关闭返回值优化,得到结果:
0x7ffc22247b74:default constructor
0x7ffc22247b78:default constructor
0x7ffc22247b44:default constructor
0x7ffc22247b7c:copy constructor
0x7ffc22247b44:destructor
=====================
0x7ffc22247b7c:destructor
0x7ffc22247b78:destructor
0x7ffc22247b74:destructor
右值引用就是把右值变成左值,通常实在C++返回值上,对于自定子类的重复拷贝做了重要改善,大大提高了C++的效率。 右值引用的概念是C++中的重要概念!!!!。
左值和右值的转换
左值变右值
move()可以通过man手册查看。
变成只读,也是不能放在等号左边
右值变左值
-
通过右值引用&& -
通过通用转换 forward<B&>
|