左值是表達式結束後依然存在的持久對象,既能出如今等號左邊也能出如今等號右邊的變量或表達式
右值是由於聲明結束後會被銷燬,因此不能放在等號左邊ios
#include <iostream> using namespace std; void Print(string& s){ cout << s; } int main(){ string s="abc"; Print(s); // OK Print("abc"); // parse error }
&是c++裏的左值引用
&&是c11裏的右值引用c++
string Proc() { return string("abc"); } int main() { const string& ref = Proc(); //此時右值的生命週期延長了,直到main函數結束 cout << ref << endl; return 0; }
使用std::move()接受一個參數,返回該參數對應的右值引用函數
template<typename _Tp> inline typename std::remove_reference<_Tp>::type&& move(_Tp&& __t) { return static_cast<typename std::remove_reference<_Tp>::type&&>(__t); } static_cast是一個強制類型轉換符,強制類型轉換會告訴編譯器:咱們知道而且不會在乎潛在的精度損失。
//下面有一個move使用的小例子 void swap(T& a, T& b) { T tmp = move(a); a = move(b); b = move(tmp); //能夠看出相比較以前的進行了屢次資源拷貝、銷燬的swap //在swap裏使用move只是進行了三次的指針交換,效率提高 }
forward()接收一個參數,返回該參數原本所對應的類型的引用。(即完美轉發)spa
#include <iostream> //#include <utility> //for std::forward using namespace std; void print(const int& t) { cout <<"lvalue" << endl; } void print(int&& t) { cout <<"rvalue" << endl; } template<typename T> void Test(T&& v) //v是Universal引用 { //不完美轉發 print(v); //v具備變量,自己是左值,調用print(int& t) //完美轉發 print(std::forward<T>(v)); //按v被初始化時的類型轉發(左值或右值) //強制將v轉爲右值 print(std::move(v)); //將v強制轉爲右值,調用print(int&& t) } int main() { cout <<"========Test(1)========" << endl; Test(1); //傳入右值 int x = 1; cout <<"========Test(x)========" << endl; Test(x); //傳入左值 cout <<"=====Test(std::forward<int>(1)===" << endl; Test(std::forward<int>(1)); //T爲int,以右值方式轉發1 //Test(std::forward<int&>(1)); //T爲int&,需轉入左值 cout <<"=====Test(std::forward<int>(x))===" << endl; Test(std::forward<int>(x)); //T爲int,以右值方式轉發x cout <<"=====Test(std::forward<int&>(x))===" << endl; Test(std::forward<int&>(x)); //T爲int,以左值方式轉發x return 0; } /*輸出結果 e:\Study\C++11\16>g++ -std=c++11 test2.cpp e:\Study\C++11\16>a.exe ========Test(1)======== lvalue rvalue rvalue ========Test(x)======== lvalue lvalue rvalue =====Test(std::forward<int>(1)=== lvalue rvalue rvalue =====Test(std::forward<int>(x))=== lvalue rvalue rvalue =====Test(std::forward<int&>(x))=== lvalue lvalue rvalue */