c++11右值引用的繫結規則
右值引用的繫結規則
右值引用(rvalue reference,&&)跟傳統意義上的引用(reference,&)很相似,為了更好地區分它們倆,傳統意義上的引用又被稱為左值引用(lvalue reference)。下面簡單地總結了左值引用和右值引用的繫結規則(函式型別物件會有所例外):
(1)非const左值引用只能繫結到非const左值;
(2)const左值引用可繫結到const左值、非const左值、const右值、非const右值;
(3)非const右值引用只能繫結到非const右值;
(4)const右值引用可繫結到const右值和非const右值。
測試例子如下:
struct A { A(){} };
A lvalue; // 非const左值物件
const A const_lvalue; // const左值物件
A rvalue() {return A();} // 返回一個非const右值物件
const A const_rvalue() {return A();} // 返回一個const右值物件// 規則一:非const左值引用只能繫結到非const左值
A &lvalue_reference1 = lvalue; // ok
A &lvalue_reference2 = const_lvalue; // error
A &lvalue_reference3 = rvalue(); // error
A &lvalue_reference4 = const_rvalue(); // error// 規則二:const左值引用可繫結到const左值、非const左值、const右值、非const右值
const A &const_lvalue_reference1 = lvalue; // ok
const A &const_lvalue_reference2 = const_lvalue; // ok
const A &const_lvalue_reference3 = rvalue(); // ok
const A &const_lvalue_reference4 = const_rvalue(); // ok// 規則三:非const右值引用只能繫結到非const右值
A &&rvalue_reference1 = lvalue; // error
A &&rvalue_reference2 = const_lvalue; // error
A &&rvalue_reference3 = rvalue(); // ok
A &&rvalue_reference4 = const_rvalue(); // error// 規則四:const右值引用可繫結到const右值和非const右值,不能繫結到左值
const A &&const_rvalue_reference1 = lvalue; // error
const A &&const_rvalue_reference2 = const_lvalue; // error
const A &&const_rvalue_reference3 = rvalue(); // ok
const A &&const_rvalue_reference4 = const_rvalue(); // ok// 規則五:函式型別例外
void fun() {}
typedef decltype(fun) FUN; // typedef void FUN();
FUN & lvalue_reference_to_fun = fun; // ok
const FUN & const_lvalue_reference_to_fun = fun; // ok
FUN && rvalue_reference_to_fun = fun; // ok
const FUN && const_rvalue_reference_to_fun = fun; // ok
【說明】:(1) 一些支援右值引用但版本較低的編譯器可能會允許右值引用繫結到左值,例如g++4.4.4就允許,但g++4.6.3就不允許了,clang++3.2也不允許,據說VS2010 beta版允許,正式版就不允許了,本人無VS2010環境,沒測試過。
(2)右值引用繫結到字面值常量同樣符合上述規則,例如:int &&rr = 123;,這裡的字面值123雖然被稱為常量,可它的型別為int,而不是const int。對此C++03標準文件4.4.1節及其腳註中有如下說明:
If T is a non-class type, the type of the rvalue is the cv-unqualified version of T.
In C++ class rvalues can have cv-qualified types (because they are objects). This differs from ISO C, in which non-lvalues never have cv-qualified types.
因此123是非const右值,int &&rr = 123;語句符合上述規則三。