C11中有左值引用和右值引用
左值引用
對一個變量的別名,不會調用拷貝構造,對別名的操作影響原值
eg:

運行結果:

右值引用
對匿名變量的引用,提出右值引用的原因:充分利用在函數調用過程中產生的臨時變量,對這個臨時變量達到最大限度的使用率
常用的匿名變量(對象):
fun(A a()); //此時生產了一個臨時變量,且無名,這就是右值
int add(int a, int b)
{
return (a + b); //此時的(a+b)的結果就是一個臨時變量,且無名,這就是右值
}
右值引用如何使用
並不是變量自動就會變成右值引用,需要用戶按右值引用的方式定義接口、定義變量,才會觸發右值引用,舉個例子:
1)
fun (A a) { //再怎么傳也不會變成右值引用
//TODO
}
如果用戶使用 fun(A()); //則就是調用一個普通的函數
2)
如果想使用右值引用就需要用戶按右值引用定義接口,才會調用到這個右值引用
fun(A&& a){
//TODO
}
fun(A()); //這時編譯器發現你有定義相關接口,就會去調用右值引用的函數了
記住: 右值引用可以優化過程中產生的臨時變量,但並不代表你什么都不做它就能優化,如果你想優化,需要你手動實現相關接口才行; 右值引用只是一個功能,你可以選擇用或不用。
上面1)和2)說的都是調用函數中的形參問題,下面說說變量問題;
int a=2, b=3;
int c = add(a, b); //c就是再普通不過的一個左值,add先產生一個臨時變量然//后再將臨時變量賦值給c
int&& d = add(a, b); //d就是一個右值,add過程中產生一個臨時變量,d就是這//個臨時變量的一個“引用”,加引號是因為說d是一個偷盜//者更合適,它把那個臨時變量給偷過來了
注意:此處使用int並不是很明顯,如果使用一個T,T中包含指針數組,大家可能更容易明白
上面的c和d是程序員用戶自己寫的,他不在乎過程中多一次拷貝就按c的方式寫;如果他是一個處女座的程序員,他可能更喜歡使用d的方式;再次重申:右值引用是一功能選項,你可以選擇用與不用。
擴展一
上面說的都是最正常的情況,即只對匿名變量(對象)使用右值引用,但是我們總是喜歡知道了一個規則后,就千方百計利用這個規則,比如下面這種使用場景:
void test(){
T t;
fun(std::move(t)); //將t轉換成了一個右值引用
}
void fun(T& t); //左值引用
void fun(T&& t); //右值引用
舉一個可能用到的場景:
void print_(std::string& str) {
std::cout<<str<<”\n”;
}
void print_(std::string&& str) {
std::cout<<str<<”\n”;
}
void test() {
std::string str(“Hello World!”);
print_(str); //左值引用,后面str內容不變
print_(std::move(str)); //轉為右值引用 ,表示str可以被移動,但是否移動看后面接口的選擇了,由於此處僅是調用一個接收右值引用傳遞的方法,
//並不會修改str,即並沒有進行move操作,所以調用完成后str內容不會發生改變
}
注意std::move的本質,它其實就是一個轉換函數,將給定的類型轉化為右值引用,而並不是真正地“移動”了資源.
