1. 程式人生 > >左值引用"&"、右值引用"&&"以及它們之間的轉換

左值引用"&"、右值引用"&&"以及它們之間的轉換

C++11中的一個新特性就是右值引用和左右值之間的轉移語義。在此之前,C++中右值引用是不被允許的。增加右值引用和轉移語義這兩個特效能夠使程式碼更加簡潔高效。

新特性的目的

右值引用 (Rvalue Referene) 是 C++ 新標準 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它實現了轉移語義 (Move Sementics) 和精確傳遞 (Perfect Forwarding)。它的主要目的有兩個方面:
(1) 消除兩個物件互動時不必要的物件拷貝,節省運算儲存資源,提高效率。
(2) 能夠更簡潔明確地定義泛型函式。

左值與右值的定義

C++( 包括 C) 中所有的表示式和變數要麼是左值,要麼是右值。通俗的左值的定義就是非臨時物件,那些可以在多條語句中使用的物件。所有的變數都滿足這個定義,在多條程式碼中都可以使用,都是左值。右值是指臨時的物件,它們只在當前的語句中有效。請看下列示例 :
簡單的賦值語句:
int i=233;


在這條語句中,i 是左值,233是臨時值即右值。在此後的程式中,i 可以被引用,233不可以引用,並且立即數都是右值。
在 C++11 之前,右值是不能被引用的,最大限度就是用常量引用繫結一個右值,如 :

 const int &a = 1;//左值的宣告符號為”&”

一般情況下,右值不能被改動。如果要改動可以這樣:

F().set().get();

F是一個類,set 是一個函式為 F中的一個變數賦值,get 用來取出這個變數的值。在這句中,F() 生成一個臨時物件,就是右值,set() 修改了變數的值,也就修改了這個右值。這樣很麻煩,效能反而不能提升還降低了程式碼的簡潔性。因此C++11中增加的右值引用能夠方便地解決實際工程中的問題,實現非常有吸引力的解決方案。

左值和右值的語法符號

左值的宣告符號為”&”, 右值的宣告符號為”&&”。
示例程式 :

void processValue(int &i,int && j)
{
    printf("%d %d\n", i,j);
}
void main(){
    int a = 2;
    processValue(a, 233);
}

程式執行後輸出2 233,但是如果將a 和 233調換位置,編譯就會出現錯誤,因為非常量引用必須為左值而右值引用也無法繫結到左值。從執行的結果看,臨時物件是作為右值處理的,但是如果臨時物件通過一個接受右值的函式傳遞給另一個函式時,就會變成左值

,因為這個臨時物件在傳遞過程中,變成了命名物件。
例項程式:

void processValue(int & j)
{
    printf("L%d", j);
}
void processValue(int && j)
{
    printf("R%d", j);
}
void processTest(int &&i)
{
    processValue(i);
}

void FunctionView(){
    int a = 2;
    processTest(2);
}

程式執行後輸出的是L2。

轉移語義的定義

右值引用是用來支援轉移語義的。轉移語義可以將資源 ( 堆,系統物件等 ) 從一個物件轉移到另一個物件,這樣能夠減少不必要的臨時物件的建立、拷貝以及銷燬,能夠大幅度提高 C++ 應用程式的效能。臨時物件的維護 ( 建立和銷燬 ) 對效能有嚴重影響。
轉移語義是和拷貝語義相對的,可以類比檔案的剪下與拷貝,當我們將檔案從一個目錄拷貝到另一個目錄時,速度比剪下慢很多。
通過轉移語義,臨時物件中的資源能夠轉移其它的物件裡。
在現有的 C++ 機制中,我們可以定義拷貝建構函式和賦值函式。要實現轉移語義,需要定義轉移建構函式,還可以定義轉移賦值操作符。對於右值的拷貝和賦值會呼叫轉移建構函式和轉移賦值操作符。如果轉移建構函式和轉移拷貝操作符沒有定義,那麼就遵循現有的機制,拷貝建構函式和賦值操作符會被呼叫。

標準庫函式 std::move

標準庫提供了函式 std::move,這個函式以非常簡單的方式將左值引用轉換為右值引用。編譯器只對右值引用才能呼叫轉移建構函式和轉移賦值函式,而所有命名物件都只能是左值引用,如果已知一個命名物件不再被使用而想對它呼叫轉移建構函式和轉移賦值函式,也就是把一個左值引用當做右值引用來使用

void processValueL(int & j)
{
    printf("L%d", j);
}
void processValueR(int && j)
{
    printf("R%d", j);
}

void main(){
    int a = 2;
    processValueL(a);
    processValueR(std::move(a));

}

執行程式後輸出L2R2。
std::move的一個重要作用就是提高資料交換的效能,使用std::move後就能夠避免使用拷貝了。

void FunSwap(int a, int b)
{
    int tmp(std::move(a));
    a = std::move(b);
    b = std::move(tmp);
}

移動比拷貝速度要快很多,這對與那些需要大量資料交換的場合來說很有用。

總結

右值引用,表面上看只是增加了一個引用符號,但它對 C++ 軟體設計和類庫的設計有非常大的影響。它既能簡化程式碼,又能提高程式執行效率。每一個 C++ 軟體設計師和程式設計師都應該理解並能夠應用它。我們在設計類的時候如果有動態申請的資源,也應該設計轉移建構函式和轉移拷貝函式。在設計類庫時,還應該考慮 std::move 的使用場景並積極使用它。在使用之前,需要檢查一下編譯器的支援情況。

相關推薦

引用"&"引用"&&"以及它們之間轉換

C++11中的一個新特性就是右值引用和左右值之間的轉移語義。在此之前,C++中右值引用是不被允許的。增加右值引用和轉移語義這兩個特效能夠使程式碼更加簡潔高效。 新特性的目的 右值引用 (Rvalue Referene) 是 C++ 新標準 (C++11,

39.引用引用

1、左值和右值的概念          左值是可以放在賦值號左邊可以被賦值的值;左值必須要在記憶體中有實體;          右值當在賦值號右邊取出值賦給其他變數的值;右值可以在記憶體也可以

引用引用

1、左值和右值的概念          左值是可以放在賦值號左邊可以被賦值的值;左值必須要在記憶體中有實體;          右值當在賦值號右邊取出值賦給其他變數的值;右值可以在記憶體也可以在C

引用引用

一、c++中的左值和右值 誤區:左值位於等號左邊,右值位於等號右邊。 C++11中的定義:左值表示式表示的是一個物件的身份(在記憶體中的位置),而右值表示式表示的是物件的值(內容)。 左值和右值都是針對表示式而言的,左值是持久的,右值是短暫的:左值在表示式結束後仍然存在,右

深刻理解引用const引用引用的本質

引用的本質是什麼?引用本質是變數的別名?其實這種說法有小問題 一,引用的本質 class A { int &a; }; class B { }; int main() { using std::cout; using s

[轉載][C++]C++11 引用詳解

找到 延長 引用 () 字面量 別名 賦值 例子 左值 我之前以為左值就是等號左邊的值,右值就是等號右邊的值。 我 太天真 ?_? 原文地址:https://blog.csdn.net/hyman_yx/article/details/52044632 (侵刪 ------

C++11 引用詳解(轉載)

左值、右值 在C++11中所有的值必屬於左值、右值兩者之一,右值又可以細分為純右值、將亡值。在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、沒有名字的就是右值(將亡值或純右值)。舉個例子,int a = b+c, a 就是左值,其有變數名為a,通過&a

引用 & C++11中

我們先來談談C++11中對左右值的判斷標準,以及左右值本身的一些細節,我想這應該是故事的開始。    在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、沒有名字的就是右值。    舉個例子:在a=b+c;中,&a是允許的操作,但&(b+c)這樣的操

C++11 引用詳解

左值、右值 在C++11中所有的值必屬於左值、右值兩者之一,右值又可以細分為純右值、將亡值。在C++11中可以取地址的、有名字的就是左值,反之,不能取地址的、沒有名字的就是右值(將亡值或純右值)。舉個例子,int a = b+c, a 就是左值,其有變數名為a

引用引用(2)

表示式可以分為以下值類別之一: 左值Lvalue:如果表示式不是const限定的,則表示式可以出現在賦值表示式的左側。 x值:要過期的右值引用。 右值(Prvalue) rvalue:非xvalue表示式,僅出現在賦值表示式的右側。Rvalues包括xvalues和

C++ 引用

看到這個type-id && cast-expression ,對於熟悉C語言的我有點發懵。 感覺就是C++的概念確實比C語言繁雜細膩的多,這個右值,就是非常的細膩區分變數的生存時間和記憶體的使用的概念,有必要理解清楚。 左值、右值 在C++11

與常引用

程式碼編譯執行環境:VS2017+Win32+Debug 1.左值的定義 左值(Lvalue)是C++中的一個基本概念,指可定址的非只讀表示式。通俗來講,凡是可以出現在賦值運算子左邊的表示式都是左值。與左值相對的就是右值(Rvalue),只能出現在賦

引用引用

開發 左值 優化 語法 表達 3.2 右值 實現 規則 1、左值和右值的概念 左值是可以放在賦值號左邊可以被賦值的值;左值必須要在內存中有實體; 右值當在賦值號右邊取出值賦給其他變量的值;右值可以在內存也可以在CPU寄存器。

C++引用引用

分配內存 右值 markdown type 提高 指向 區分 基本語法 down 1.左值和右值概念: 左值是可以放在賦值號左邊可以被賦值的值:左值就是指在表達式使用完之後仍存在的對象(存儲空間); 右值當在賦值號右邊去除值賦給其他變量的值:右值可以在內存也可以在CPU寄存

細談 C++ 返回傳的三種方式:按返回按常量引用返回以及引用返回

一、引言 停滯了很久,最近又開始細細品味起《Data Structure And Algorithm Analysis In C++》這本書了。這本書的第一章即為非常好的 C++11 統領介紹的教材範文,可能對於 C++11 新手來說,作者這樣短篇幅的介紹或許有些蒼白晦澀,但是對於我

C++ 11 引用引用,std::move, std::foward

這篇文章要介紹的內容和標題一致,關於C++ 11中的這幾個特性網上介紹的文章很多,看了一些之後想把幾個比較關鍵的點總結記錄一下,文章比較長。給出了很多程式碼示例,都是編譯執行測試過的,希望能用這些幫助理解C++ 11中這些比較重要的特性。 關於左值和右值的

C++11:引用引用

C++11:左值引用與右值引用 在 C++11 的新標準中,出現了「右值引用」的說法,既然有了右值引用,那麼傳統的引用也就叫做左值引用。 右值引用 (Rvalue Referene) 是 C++ 新標準 (C++11, 11 代表 2011 年 ) 中引入的新特性 , 它實現了轉

14.C++11 新標準:foreach引用&&lambda表示式語言級別的執行緒與鎖

關鍵字和新語法 1、delete      指定刪除類的成員方法         在類的成員方法後面寫  = delete  就將該成員方法刪除,使用者無法呼叫。 智慧指標unique_ptr就是將物件的拷貝構造和operator=  delete刪除了 2、auto

C++引用引用引用

特點: 引用:引用本質指標實現。 引用一旦初始化, 不會引用其他變數。        右值引用目的:快速建立暫存器資料的引用,就是還沒有記憶體實體的資料可以立即建立一個引用。 (一般寫模板函式有一個左值引用的模板函式,都會對應一個右值引用的模板函式,即使實現程式碼是相同的。

C++——引用引用

   這篇blog主要介紹一下左值和右值的概念及應用陷阱 1、左值和右值的概念          左值是可以放在賦值號左邊可以被賦值的值;左值必須要在記憶體中有實體;          右值當在賦值號