C++11:右值引用

左值、右值,和右值引用

左值(lvalue)右值(rvalue)是编译器和程序中常出现的词汇,一个最为典型的判别左值右值的方法是,在赋值表达式中,出现在等号左边的就是左值,出现在等号右边的就是右值。例如
a = b + c;
在这个表达式中,a就是左值,b+c就是右值。
不过 C++中还有另一种被广泛认同的说法:可以取地址的、有名字的就是左值;不能取地址的、没有名字的就是右值。
上述表达式a = b + c;中,a是可以取地址的,即&a,但如果对(b+c)取地址&(b+c)则无法通过编译。因此a是左值,(b+c)是右值。

C++11中右值的判定

C++11中,右值由两个概念构成一个是将亡值,一个是纯右值。

纯右值

纯右值,是用于辨识临时变量和一些不跟对象关联的值。比如
1. 非引用返回的函数返回的临时变量(A getA( ){ })
2. 运算表达式(1+3产生的临时变量)
3. 不跟对象关联的字面量值(1,’a’,true等)
4. 类型转换函数的返回值
5. lambda表达式

将亡值

将亡值,是C++11新增的跟右值引用相关的表达式,这样表达式通常是将要被移动的对象,比如:
1. 返回右值引用T&&的函数的返回值
2. std::move()的返回值
3. 转换为T&&的类型转换函数的返回值。
剩余的,可以标识函数、对象的值都属于左值。
在C++11中,所有的值都必然属于左值、将亡值和纯右值之一。

右值引用

C++11中,右值引用就是对一个右值进行引用的类型。因为右值通常是匿名变量,所以只能通过右值引用来找到它。通常情况下,只能通过右值表达式&&获得其引用。

//假设GetRValue()返回一个右值
class Foo;
Foo GetRValue(){
    return Foo();
}
Foo && a = GetRValue();
Foo b = GetRValue();

对于上面两行代码,第一行是右值引用,第二行是赋值。
对于GetRValue(),在函数内部建立了一个Foo临时对象。当使用右值引用时,a会直接绑定函数返回的临时变量。本来应该在函数结束时释放的临时变量此时将与a的生命周期相同。当简单的运用赋值操作时,将会重新分配一块内存和b绑定,再调用一次Foo的构造函数复制临时变量的内容,最后再释放临时 变量的内存。这样会多一次构造和析构的过程。
值得一提的是,无论是左值引用还是右值引用,都要在声明之后立即进行初始化操作。左值引用是具名变量值的别名,右值引用是不具名(匿名)变量的别名。
这里区分一下:

引用类型 语法
左值引用 T & lref
右值引用 T && rref

你可能感兴趣的:(C++)