C 左值引用和右值引用

2021-08-18 06:24:55 字數 2646 閱讀 1304

1.左值和右值概念:

左值是可以放在賦值號左邊可以被賦值的值:左值就是指在表示式使用完之後仍存在的物件(儲存空間);

右值當在賦值號右邊去除值賦給其他變數的值:右值可以在記憶體也可以在cpu暫存器。

可以簡單的認為左值就是具有名稱的物件,所有的變數(包括const修飾的變數)都是左值。而右值指的是那些在表示式使用完之後就不再存在的儲存空間,實際上所有的臨時變數表示式都是右值:如下解釋了左值和右值的區別:

int x=3+4;//x是左值,3+4是右值,3+4的結果存放在臨時物件中,在表示式之外這些空間都是不可訪問的。
乙個物件被用作右值時,使用的是它的內容(值),被當作左值時,使用的是它的位址。
2.引用

引用是c++語法做的優化,引用的本質還是靠指標來實現的。引用相當於變數的別名。

引用可以改變指標的指向,還可以改變指標所指向的值。

引用的基本規則:

1)宣告引用的時候必須初始化,且一旦繫結,不可把引用繫結到其他物件;即引用必須被初始化,不能對引用重新定義;

2)對引用的一切操作,就相當於對原物件的操作。

3.左值引用和右值引用:

左值引用的基本語法: type &引用名=左值表示式;

右值引用的基本語法:type &&引用名= 右值表示式;

4.右值引用用來解決以下兩種問題:

1)移動語義:

移動語義允許程式設計師將資源(比如動態分配記憶體)從乙個物件移動到另乙個物件,這將大大提高程式的效能,注意這裡是移動而非複製。右值引用可以支援移動語義,是因為 它允許資源從臨時物件移動出來,而初次之外是無法引用臨時物件(右值)的。

當對右值進行操作時,右值本身往往沒有必要保留,因此在有些情況下,右值資源可以直接移動給其他物件。通過右值引用,程式可以明確的區分出傳入的引數是否為右

值,從而避免不必要的複製,因而可以提高程式的效率。下面考慮std庫內的實現資料交換的swap()函式,假設x是乙個已經實現備份建構函式即備份賦值運算子的類:

templatet>

void swap(t& a,t%b)

x a,b;

swap(a,b);

這裡沒有使用右值,所以swap()函式內的3行**都沒有使用移動語義,每一行都需要資料備份。

在c++0x中的std庫將引入乙個新的std::move()函式,這個函式只是簡單的將引數轉化為右值。

所以在c++0x中,std庫內的swap()函式將程式設計類似於下面的實現:

templatevoid swap(t& a,t& b)

x a,b;

swap(a,b);

通過呼叫std::move()函式引入右值引用,使得swap()函式的3個語句具有移動語義,這樣便消除了資料備份操作,只會將源物件移動到目標物件。

2)完美**:

完美**技術能夠有效消除函式過載的需求並避免**問題。當編寫乙個將引用作為它的引數的通用函式,並且這個引數將被傳遞(或**)給另乙個函式時,往往會出現**問題。比如,如果乙個通用函式要求的引數型別為const t&,這意味著被呼叫函式不能修改該引數的值;如果通用函式要求引數型別為t&,則不能使用右值(比如臨時物件或乙個整型常熟)來呼叫。

一般情況下,為了解決這個問題,需要分別定義這個函式的兩種不同過載形式,分別帶t&和const t&引數,這樣的後果是,隨著通用函式所帶引數的個數增加,需要的不同過載形式將呈指數成倍增加。而右值引用允許程式設計師只寫一種版本的函式,就可以接受任意的引數,並將它們**給其他的函式,就好像直接呼叫函式一樣。

考慮下面例子中定義的4種引數型別w、x、y、z,它們的建構函式分別需要const及非const的左只引用作為引數:

struct w

};struct x

};struct y

};struct z

};

現在假設想寫乙個產生物件的通用函式,其中一種寫法如下:

template

t* factory(a1& a1,a2& a2)

下面**演示了對factory()函式的合法呼叫方式:

int a=4,b=5

;w* pw=factory(a,b);

但是下面的**種對factory的呼叫是非法的,因為factory()函式要求將左值引用作為引數,但卻通過右值來呼叫:

z* pz=factory(2,2);
通常解決這個問題的辦法是,建立分別處理t&及const t&的過載函式。右值引用允許程式設計師只寫factory()函式的一種版本,如下所示:

templatet,typename a1,typename a2>

t* factory(a1&& a1,a2&& a2)

這裡使用右值引用作為factory()函式的引數,而std::forward()函式的目的就是將床底給factory()函式的引數**給模板類的構造器。

下面的**進一步演示了可以使用不同的方式來呼叫factory()函式分別產生不同類的物件,而這些呼叫引數總能被正確**給合適的類構造器:

int main()

C 左值和右值,左值引用和右值引用

c 對於左值和右值沒有標準定義,但是有乙個被廣泛認同的說法 可見立即數,函式返回的值等都是右值 而非匿名物件 包括變數 函式返回的引用,const物件等都是左值。從本質上理解,建立和銷毀由編譯器幕後控制,程式設計師只能確保在本行 有效的,就是右值 包括立即數 而使用者建立的,通過作用域規則可知其生存...

c 左值 右值 右值引用 左值引用

c 裡一切值必須屬於左值 右值兩者之一。左值 一切變數 包括用const修飾的變數 物件 包括引用都屬於左值 右值 一切字面值 可以是巨集 臨時無名物件 函式返回值 表示式 如a n 說明一下 函式返回值,返回的是某乙個型別的值,並不是返回變數。左值並不是說能放在 左邊的值就是左值 雖然用const...

c 左值 右值 左值引用 右值引用

在c語言中,左值認為是賦值語句的左側,右值認為是賦值語句的右側。在c 中,意義稍有不同。c 中,每乙個表示式會產生乙個左值或者右值,相應的,該表示式也就被稱作 左值表示式 右值表示式 乙個左值表示式的求值結果是乙個物件或者是乙個函式。左值可以當右值使用,而右值不能當左值使用。c prime 中這麼簡...