左值、右值
在C语言中,我们常常会提起左值(lvalue)、右值(rvalue)这样的称呼。一个最为典型的判别方法就是,在赋值表达式中,出现在等号左边的就是“左值”,而在等号右边的,则称为“右值”。如:
int b = 1;
int c = 2;
int
在这个赋值表达式中,a就是一个左值,而b + c则是一个右值。
不过C++中还有一个被广泛认同的说法,那就是可以取地址的、有名字的就是左值,反之,不能取地址的、没有名字的就是右值。那么这个加法赋值表达式中,&a是允许的操作,但&(b + c)这样的操作则不会通过编译。因此a是一个左值,(b + c)是一个右值。
相对于左值,右值表示字面常量、表达式、函数的非引用返回值等。
左值引用、右值引用
左值引用是对一个左值进行引用的类型,右值引用则是对一个右值进行引用的类型。
左值引用和右值引用都是属于引用类型。无论是声明一个左值引用还是右值引用,都必须立即进行初始化。而其原因可以理解为是引用类型本身自己并不拥有所绑定对象的内存,只是该对象的一个别名。
左值引用是具名变量值的别名,而右值引用则是不具名(匿名)变量的别名。
左值引用:
int &a = 2; // 左值引用绑定到右值,编译失败, err
int b = 2; // 非常量左值
const int &c = b; // 常量左值引用绑定到非常量左值,编译通过, ok
const int d = 2; // 常量左值
const int &e = c; // 常量左值引用绑定到常量左值,编译通过, ok
const int &b = 2; // 常量左值引用绑定到右值,编程通过, ok
“const 类型 &”为 “万能”的引用类型,它可以接受非常量左值、常量左值、右值对其进行初始化。
右值引用,使用&&表示:
int && r1 = 22;
int x = 5;
int y = 8;
int
通常情况下,右值引用是不能够绑定到任何的左值的。
int c;
int && d = c; //err
测试示例:
#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;
}
运行结果如下:
参考资料:
1、C++11 标准新特性: 右值引用与转移语义
2、深入理解C++11:C++11新特性解析与应用