背景
在C++11中添加了几个概念:左值,右值,左值引用,右值引用。这几个概念非常抽象,只能尽力去解释和阐述。
左值
左值 = 内存 + 名字 + 地址 
int a = 1
a = 2;
printf("%d\n", a = 3);
右值
左值 = 内存 + 地址 
int a = 1
左值引用
给有名字的内存额外起一个别名 ,需要用语法& 
int a = 1;
int& b = a;
右值引用
给没名字的内存(右值)起一个名字,需要用语法&&
int&& a = 1;

可以发现,一旦给右值起了一个名字,就会发现右值变成了左值(名字+内存+地址),这个要好好理解。
const引用

const int& a = 3;
我们知道3是右值,而&是给一个有名字的内存(左值)取一个别名, 为了能给右值起别名 ,看清楚是起别名,不是起名字,因为起名字用&&就可以。这里可以通过const加一个限制,那么就可以给3起别名 了,尽管3就一个名字。留一个问题,现在的a是左值还是右值?(答案是左值,因为满足了左值条件)
测试
既然我们已经学完1+1=2了,那么下面开始来解一元二次方程了!
demo_1
int& a = 3;
会编译报错,为什么?因为3是一个右值,而&是给左值起一个额外的名字,所以编译报错。
demo_2
int a = 4;
int &&b = a;
会编译报错,为什么?因为a是一个左值,而&&是给右值起第一个名字,你都有名字了还来用&&凑热闹,所以编译报错。
demo_3
int a = 4;
int &b = a * 2;
会编译报错,为什么?因为a是一个左值,a *2 这里是利用了a的右值属性,所以a *2 会生成一个没有名字的右值,你去给一个没有名字的内存块取别名是不行的,因为他都没有名字,何来别名一说?所以你只能用&&给他取一个名字
move语义
move的意思是把左值的名字移出掉(其实还是可以用a去调用),所以会变成右值,因此一个左值一旦用了move, 最好保证它在move后不要再被调用,毕竟move的思想就是把名字除去了,毕竟都被除名了,也就是想表达以后我不会再叫你a了。 
#include <iostream>
using namespace std;
void Show(int&& para)
{
cout<<para<<endl;
para = 4;
}
int main()
{
int a = 5;
Show(3);
Show(a);
Show(move(a));
cout<<a<<endl;
return 0;
}
|