为了支持移动操作,新标准引入了一种新的引用类型–右值引用。所谓右值引用就是必须绑定到右值的引用。我们可以通过&&来获得幼稚引用
1.左值和右值的定义
左值和右值都是表达式的属性。一般而言,左值表达式表示的是一个对象的身份,而右值表达式表示的是一个对象的值
例如
int i=3;
在这里i就是一个左值,它代表了自己是个int型变量(一种身份),而3则仅仅是一个值,所以其为右值。一般来说,右值为一个临时的值,我们取不到其地址,例如上面的3,而左值我们可以获得其地址,上面的i就是这样
2.如何确定用哪种引用
我们先来看几个例子吧
9 #include<iostream>
10 #include<vector>
11 #include<string>
12
13 int main(int argc,char **argv)
14 {
15 int i = 3;
16 int &r = i;
17 int &&rr = i;
18 int &t = i*42;
19 int &&tt = i*42;
20 return 0;
21 }
编译上面的例子结果如下
可以看出当第17行我们给右值引用赋一个左值i时报错
当第18行我们给左值引用t赋一个临时的右值时也报错
从上面的例子我们不难发现,左值引用只可以引用左值类型,右值引用也只可以引用右值
3.左右值的区别
通过上面的叙述,我们可以得出来,左值为一个持久的对象,而右值为临时对象,由于右值引用绑定的为右值(临时对象),我们可以得出
.所引用的对象将要销毁
.该对象没有其他用户
这俩个特性意味着,使用幼稚引用的代码可以自由的接管所引用对象的资源
4.新标准库move函数
根据上面判断左右值的方法,我们不难得出变量为一个左值。那么有什么办法使其可以变为一个右值呢?std::move就派上了用场,该函数,可以将一个左值转换为对应的右值引用类型
具体实例如下
22 #include<iostream>
23 #include<vector>
24 #include<string>
25 #include <utility>
26
27 int main(int argc,char **argv)
28 {
29 int i = 3;
30 int &&rr = std::move(i);
31 return 0;
32 }
调用了move函数就意味着我们和编译器做了一个约定:我想把这个左值像右值一样来处理它,之后我们除了重新赋值和销毁之外,我们将不在使用它