11-右值引用
18.1.9 右值引用
传统的C++引用(现在称为左值引用)使得标识符关联到左值。左值是一个表示数据的表达式(如变量名或解除引用的指针),程序可获取其地址。最初,左值可出现在赋值语句的左边,但修饰符const的出现使得可以声明这样的标识符,即不能给它赋值,但可获取其地址:
int n;
int * pt = new int;
const int b = 101; // can't assign to b, but &b is valid
int & rn = n; // n identifies datum at address &n
int & rt = *pt; // *pt identifies datum at address pt
const int & rb = b; // b identifies const datum at address &b
C++11新增了右值引用(这在第8章讨论过),这是使用&&表示的。右值引用可关联到右值,即可出现在赋值表达式右边,但不能对其应用地址运算符的值。右值包括字面常量(C-风格字符串除外,它表示地址)、诸如x + y等表达式以及返回值的函数(条件是该函数返回的不是引用):
int x = 10;
int y = 23;
int && r1 = 13;
int && r2 = x + y;
double && r3 = std::sqrt(2.0);
注意,r2关联到的是当时计算x + y得到的结果。也就是说,r2关联到的是33,即使以后修改了x或y,也不会影响到r2。
有趣的是,将右值关联到右值引用导致该右值被存储到特定的位置,且可以获取该位置的地址。也就是说,虽然不能将运算符&用于13,但可将其用于r1。通过将数据与特定的地址关联,使得可以通过右值引用来访问该数据。
程序清单18.1是一个简短的示例,演示了上述有关右值引用的要点。
程序清单18.1 rvref.cpp
// rvref.cpp -- simple uses of rvalue references
#include <iostream>
inline double f(double tf) {return 5.0*(tf-32.0)/9.0;};
int main()
{
using namespace std;
double tc = 21.5;
double && rd1 = 7.07;
double && rd2 = 1.8 * tc + 32.0;
double && rd3 = f(rd2);
cout << " tc value and address: " << tc <<", " << &tc << endl;
cout << "rd1 value and address: " << rd1 <<", " << &rd1 << endl;
cout << "rd2 value and address: " << rd2 <<", " << &rd2 << endl;
cout << "rd3 value and address: " << rd3 <<", " << &rd3 << endl;
cin.get();
return 0;
}
该程序的输出如下:
tc value and address: 21.5, 002FF744
rd1 value and address: 7.07, 002FF728
rd2 value and address: 70.7, 002FF70C
rd3 value and address: 21.5, 002FF6F0
引入右值引用的主要目的之一是实现移动语义,这是本章将讨论的下一个主题。