C++11經過std::move()和std::forward()函數分別實現了左值轉右值和完美轉發的功能。app
對於std::move(),考慮以下情形:函數
void func(int &&args) {spa
std::cout << args << std::endl;原型
}引用
int a = 10;error
func(20); // okco
func(a); // error, 右值引用不能綁定左值background
func(std::move(a)); // okreturn
對於std::forward(),完美轉發,當參數
void func(int &arg) {
std::cout << "func lvalue" << std::endl;
}
void func(int &&arg) {
std::cout << "func rvalue" << std::endl;
}
template <typename T>
void wrapper(T &&args) {
func(args);
}
int main() {
int a = 10;
wrapper(a);
wrapper(20);
return 0;
}
以上函數輸出:
func lvalue
func lvalue
雖然咱們調用wrapper()函數時,傳入的參數一個是左值,一個是右值,可是最終的輸出確都是左值。緣由是咱們在中間加了一層轉發函數wrapper()。
引用疊加,引用是能夠疊加的,對於 T &&a; 疊加規則以下:
(1)當T類型爲 Type 時,a 爲 Type &&a,右值引用。
(2)當T類型爲 Type& 時,a爲 Type &a,左值引用。
(3)當T類型爲 Type&& 時,a爲 Type &&a,右值引用。
經過引用疊加,分析以上示例可知,調用wrapper()時,wrapper(a) 是調用的原型是 wrapper(int &),是左值調用;wrapper(20)調用的原型是wrapper(int &&),是右值調用。可是在wrapper()函數內部,不管如何,args都是一個左值,在調用func()函數的時候,調用的func()原型老是func(int &)。
所以,根本緣由實際上是,右值引用屬性不能被轉發。因此,C++11提供了std::forward()函數用於完美轉發。即,在轉發過程當中,左值引用在被轉發以後仍然保持左值屬性,右值引用在被轉發以後依然保持右值屬性。修改以後的代碼以下:
void func(int &arg) {
std::cout << "func lvalue" << std::endl;
}
void func(int &&arg) {
std::cout << "func rvalue" << std::endl;
}
template <typename T>
void wrapper(T &&args) {
func(std::forward<T>(args));
}
int main() {
int a = 10;
wrapper(a);
wrapper(20);
return 0;
}
如此,輸出以下:
func lvalue func rvalue