C++0x尝鲜:右值引用

关于C++0x

C++0x是正在酝酿中的C++语言的下一代标准,截至2009年底虽未完全定稿,但绝大部分内容已经在新草案中得以盖棺定论。新标准对语言核心内容的扩充多达四五十项,标准库的篇幅更是扩容一倍,不可不谓是C++语言标准的一次重大升级。由于C++0x标准极有可能由标准委员会于2011年底正式推出,因此如何尽快学习、应用这些新的语言特性也就自然而然地成了C++社区的新课题。
 

关于右值引用(rvalue reference)

右值引用是最早进入C++0x标准的新特性之一,也是新标准的核心特性之一。简而言之,右值引用(记作 T&& )是对右值的引用,对临时量的引用,对无名变量的引用。而传统的引用(记作 T& )则是对左值的引用,对具名变量的引用。后者在新标准中将被改称为左值引用(lvalue reference)。右值引用的引入主要用于解决移动语意(move semantics)以及泛型函数之实参的完美转发(perfect forwarding)问题,在此略过不谈。
 
新型的右值引用在表达式中须作为左值来使用,在这一点上与传统的左值引用相类似。但在绑定左右值时两者有较大差别,以下举例说明:
 

代码1

#include <string>
using namespace std;

string modifiable_rvalue() {
	return "cute";
}

const string const_rvalue() {
	return "fluffy";
}

int main() {
	string modifiable_lvalue("kittens");
	const string const_lvalue("hungry hungry zombies");

	string& a = modifiable_lvalue;          // Line 16
	string& b = const_lvalue;               // Line 17 - ERROR
	string& c = modifiable_rvalue();        // Line 18 - ERROR
	string& d = const_rvalue();             // Line 19 - ERROR

	const string& e = modifiable_lvalue;    // Line 21
	const string& f = const_lvalue;         // Line 22
	const string& g = modifiable_rvalue();  // Line 23
	const string& h = const_rvalue();       // Line 24

	string&& i = modifiable_lvalue;         // Line 26 - ERROR
	string&& j = const_lvalue;              // Line 27 - ERROR
	string&& k = modifiable_rvalue();       // Line 28
	string&& l = const_rvalue();            // Line 29 - ERROR

	const string&& m = modifiable_lvalue;   // Line 31 - ERROR
	const string&& n = const_lvalue;        // Line 32 - ERROR
	const string&& o = modifiable_rvalue(); // Line 33
	const string&& p = const_rvalue();      // Line 34
}

代码说明:
  1. modifiable_lvalue 变量和 const_lvalue 变量均为string类型的左值,其中 modifiable_lvalue 变量的值可修改,为non-const左值,而 const_lvalue 变量的值不可修改,为const左值。
  2. modifiable_rvalue 函数和 const_rvalue 函数均返回string类型的右值,其中 modifiable_rvalue 函数的返回值可修改,为non-const右值,而 const_rvalue 函数的返回值不可修改,为const右值。
  3. a,b,c,d 均为non-const左值引用,按照标准只能绑定non-const左值,因而第16行编译通过,而第17,18,19行则编译错误。
    注意:Microsoft  C++编译器的非标准扩展致使第18行在缺省情况下也能编译通过
  4. e,f,g,h 均为const左值引用,按照标准能够绑定non-const,const,左值,右值所有四种组合,因而第21,22,23,24行均编译通过。
  5. i,j,k,l 均为non-const右值引用,按照标准只能绑定non-const右值,因而第28行编译通过,而第26,27,29行则编译错误。
  6. m,n,o,p 均为const右值引用,按照标准只能绑定non-const,const右值,因而第33,34行编译通过,而第31,32行则编译错误。
  7. 以上3~6所描述的标准中的绑定策略可归纳为表1,其中最后一列为绑定优先度,用于重载决策。
  8. 为了便于记忆,下面给出判定左右引用绑定左右值是否可行的两条依据:
    non-const引用不能绑定const值,而const引用则能绑定non-const值,因为const引用可增加安全性。
    左值引用可绑定右值,右值引用却不能绑定左值,原因在于右值引用具有危险性,一旦用于转移语意其值将被悄无声息地修改。
 

表1

Expression→
Reference Type↓
T
rvalue
const T
rvalue
T
lvalue
const T
lvalue
Priority
T&& X       4
const T&& X X     3
T&     X   2
const T& X X X X 1
 

代码2

#include <iostream>
#include <string>
using namespace std;

void purr(const string& s) {
	cout << "purr(const string&): " << s << endl;
}

void purr(string&& s) {
	cout << "purr(string&&): " << s << endl;
}

string strange() {
	return "strange()";
}

const string charm() {
	return "charm()";
}

int main() {
	string up("up");
	const string down("down");

	purr(up);
	purr(down);
	purr(strange());
	purr(charm());
}

//purr(const string&): up
//purr(const string&): down
//purr(string&&): strange()
//purr(const string&): charm()

代码说明:
  1. up 变量和 down 变量分别为non-const左值和const左值。
  2. strange 函数和 charm 函数的返回值分别为non-const右值和const右值。
  3. 依据表1的绑定策略,可知
    purr(const string& s) 能够接受 up 变量和 down 变量以及 strange 函数和 charm 函数的返回值为参数,
    purr(string&& s) 则只能接受 strange 函数的返回值为参数。
  4. 依据表1的绑定优先度,可知
    尽管purr(const string& s)与purr(string&& s) 两者均能接受 strange 函数的返回值为参数,
    但对于non-const右值(此处为strange 函数的返回值),
    non-const右值引用(此处为string&& s)的绑定优先度4要高于const左值引用(此处为const string& s)的绑定优先度1,
    故 purr(strange()) 调用 purr(string&& s) 版本,
    而 purr(up),purr(down),purr(charm()) 则调用 purr(const string& s) 版本。
 

补记

代码1,2均摘自
http://blogs.msdn.com/vcblog/archive/2009/02/03/rvalue-references-c-0x-features-in-vc10-part-2.aspx。
由于新标准中关于右值引用的内容在原文发表后发生了变化,代码1在VS2010 Beta2环境下的编译结果与原文有所不同。
 
相关链接
C++0x wiki http://en.wikipedia.org/wiki/C%2B%2B0x
C++0x FAQ http://www2.research.att.com/~bs/C++0xFAQ.html
右值引用简介 http://www.artima.com/cppsource/rvalue.html
右值引用与移动语意  http://cpp-next.com/archive/2009/09/move-it-with-rvalue-references/
 

你可能感兴趣的:(C++,String,Microsoft,语言,reference,stdstring)