新特性目的
右值引用 (Rvalue Referene) 是 C++ 新标准 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它实现了转移语义 (Move Sementics) 和精确传递 (Perfect Forwarding)。它的主要目的有两个方面:
- 消除两个对象交互时不必要的对象拷贝,节省运算存储资源,提高效率。
- 能够更简洁明确地定义泛型函数。
左值、右值
在C语言中,我们经常会提起左值、右值这样的称呼。一个最为典型的判别方法就是,在赋值表达式中,出现在等号左边的就是左值,而在等号右边的,则称为右值。如:
int b = 1;
int c = 2;
int a = b + c;
在这个赋值表达式中,a就是一个左值,而b+c则是一个右值。
不过C++中还有一个被广泛认同的说法,那就是可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值。那么这个加法赋值表达式中,&a是允许的操作,但是&(b+c)这样的操作则不会通过编译。因此a是一个左值,而(b+c)是一个右值。
C++( 包括 C) 中所有的表达式和变量要么是左值,要么是右值。通俗的左值的定义就是非临时对象,那些可以在多条语句中使用的对象。所有的变量都满足这个定义,在多条代码中都可以使用,都是左值。右值是指临时的对象,它们只在当前的语句中有效。
相对于左值,右值可以表示字面常量、表达式、函数的非引用返回值等。
左值引用、右值引用
左值引用就是对一个左值进行引用,右值引用就是对一个右值进行引用的类型。
左值引用和右值引用都属于引用类型,无论是声明一个左值还是右值引用,都必须立即进行初始化,而其原因可以理解为引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。
左值引用:
int &a = 2; //err,左值引用只能引用左值
int b = 2;
const int cb = 3;
const int &c = b;
const int &e = cb;
const int &f = 2;
“const 类型 &”为万能的引用类型,他可以接受非常量左值、常量左值、右值对其进行初始化。
右值引用,使用&&表示:
int && r1 = 22;
int x = 5;
int y = 8;
int && r2 = x + y;
通常情况下,右值引用是不能够绑定到任何的左值的。
int c;
int && d = c; //err
通用引用,这是Scott Meyers自创的一个词,通俗地讲,通用引用是这样一个东西:它既能绑定左值又能绑定右值,在代码中一般长这个样子:T&&。通用引用有两个条件:
- 必须精确地满足“T&&”这种形式,不能加const等修饰。
- T必须是通过推断得到的,最常见的例如模板参数。
测试示例:
#include <iostream>
using namespace std;
void process_value(int & i) //参数为左值引用
{
cout << "LValue processed: " << i << endl;
}
void process_value(int && i) //参数为右值引用
{
cout << "RValue processed: " << i << endl;
}
int main()
{
int a = 0;
process_value(a); //LValue processed: 0
process_value(1); //RValue processed: 1
return 0;
}