c 11 右值引用與Lambda表示式

2021-10-08 11:48:49 字數 4014 閱讀 5630

lambda表示式

在c語言中,對於陣列的初始化,我們可以這樣進行

int arr=

;

允許陣列使用花括號{}的方式進行初始化,但是在c++98中的vector陣列以及一些自定義的型別中,這樣初始化還是不被允許的,而c++11對此做出了修正。

他允許verctor使用花括號{}的方式對陣列進行初始化.

vector<

int> arr2

;vector<

int> arr3 =

;

再進行初始化的過程中,陣列名和花括號中可以不新增=

支援花括號進行初始化的原因:

如果想要使用多個物件對列表進行初始化,需給該類(模板類)新增乙個帶有initializer_list型別引數的建構函式 和 =運算子的過載。

template

<

class

t>

class

vector

vector

&operator

=(initializer_list tmparr)

size_t size()

t operator

(size_t idx)

private

: t* _arr;

size_t _size;

size_t _capacity;

};

在c++中,當我們建立乙個類,這個類中會預設有六個成員函式。如果在一些特殊的場合下,我們不想讓這些預設的成員函式發生作用,我們在c++98中可以這樣來:

class

date

;

我們可以把不想存在的預設建構函式變成私有成員,並只對預設函式進行宣告不進行實現,這樣在類外就不能進行訪問,就可以去掉這個預設的建構函式了。

但是在c++11中,新增了乙個delete關鍵字,他可以取消掉預設建構函式的作用。就是在該函式宣告加上=delete即可,該語法指示編譯器不生成對應函式的預設版本,稱=delete修飾的函式為刪除函式

class

date

;

對應的還有乙個顯示預設函式。在預設函式定義或者宣告時加上=default,從而顯式的指示編譯器生成該函式的預設版本,用=default修飾的函式稱為顯式預設函式

class

date

;

c++相比c語言,提出了引用的概念,但是引用只能對乙個已經宣告的物件進行操作,給他乙個別名,引用的變數和引用的實體共用一塊記憶體空間,就相當於指標,只是我們在使用的時候不用像使用指標那樣(*p),寫法簡單。

但是對於那些臨時變數,這時使用引用是不可以的,因為他們本身就沒有名字,是乙個匿名物件。

為了解決這一問題,c++11加入了右值引用的概念,他也是乙個別名,只是他只能對右值進行使用。

int

&& num =

10;

左值,一般就是可以放在=左邊,並且可以取位址的變數

普通的變數,他們有名字,那麼就可以取位址,就可以作為左值

const 修飾的常量,雖然不可以修改,但是可以取位址,所以說也是左值

函式的返回值是引用型別,那麼也可以認為是左值

變數的引用型別,也是左值

右值,一般認為只能放在=右邊,或者不能取位址的變數

函式的返回值是乙個臨時變數,那麼就認為這是乙個右值

變數本身就是乙個臨時變數,或者匿名物件,則為右值

int a =10;

const

int& ra1 =10;

const

int& ar2 = a;

而對於const引用而言,他可以引用右值,也可以引用左值。而普通的引用只可以引用左值。

而右值引用只能引用右值,不能引用左值。

c++11中,對於拷貝構造的時候,如果所傳的引數是乙個臨時變數,那麼就會使用右值引用的方式進行操作,而emplace_back函式就是乙個對於臨時變數操作的介面,他可以完成對臨時物件的尾插操作,避免多餘的拷貝。

用基本型別(int,char)來看的話效果不是那麼明顯,使用string型別來看一下關於右值引用

我們可以看到這個過程一共呼叫了兩次拷貝構造,一次是引數的拷貝構造,一次是插入元素時的拷貝構造,這就造成了資料的利用率比較低。

這是因為const 引用既可以引用左值,也可以引用右值,所以對於左值和右值不容易區分。在c++11中使用右值引用,再加乙個函式過載就可以了。

那麼對於右值引用,只需要將他的引數(乙個臨時物件),進行swap交換一下就可以了,避免了賦值的時候再呼叫一次拷貝構造。

vector

(vector

&& tmparr)

vector

&operator

=(vector

&& tmparr)

有時候在做題的時候,經常會看到一些大佬的程式中有這樣的**

sort

(arr.

begin()

, arr.

end(),

(const

int& a,

const

int& b)

->

bool

);

而自己在寫的時候是這樣的,呼叫自己在函式外部寫的仿函式,然後進行排序

bool

(const

int& a,

const

int& b)

sort

(arr.

begin()

, arr.

end(

), cmp)

;

這就是c++11中的lambda表示式,他可以說是乙個匿名函式,在函式的內部宣告 + 使用。

他的格式如下:

[capture-list]

(parameters) mutable -> return-type

關於捕捉列表,他其實就是為了讓我們在使用lambda表示式的時候,如果想要使用當前作用域內的變數,但是又不想讓他變成引數,那麼就可以使用捕捉列表對想要使用的變數進行捕捉

內容意義

[var]

表示值傳遞方式捕捉變數var

[=]表示值傳遞方式捕獲所有父作用域中的變數(包括this)

[&var]

表示引用傳遞捕捉變數var

[&]表示引用傳遞捕捉所有父作用域中的變數(包括this)

[this]

表示值傳遞方式捕捉當前的this指標

lambda表示式與普通函式在彙編中的呼叫方式

可以看到兩種函式的呼叫的方式是相同的,都是call指令,只是lambda表示式在呼叫的時候,會自己給函式起乙個lambda的名字,然後使用call進行呼叫。

c 11 右值引用

右值引用 是一種復合型別,跟c 的傳統引用很類似。為更準確地區分兩種型別,我們把傳統的c 引用稱為 左值引用 而使用 引用 這一術語時,我們的意思同時包含兩種引用 左值引用和右值引用。右值引用的行為跟左值引用類似,不同之處在於 右值引用可以繫結到臨時量 右值 而 非const的 左值引用卻不能繫結到...

C 11 右值引用

消除兩個物件互動時不必要的物件拷貝,節省運算儲存資源,提高效率。能夠更簡潔明確地定義泛型函式。1.右值引用 int a a 1 here,a is an lvalue 上述的a就是乙個左值。c 11中左值的宣告符號為 為了和左值區分,右值的宣告符號為 printreference const str...

C 11右值引用

c 11中引入的乙個非常重要的概念就是右值引用。理解右值引用是學習 移動語義 move semantics 的基礎。而要理解右值引用,就必須先區分左值與右值。對左值和右值的乙個最常見的誤解是 等號左邊的就是左值,等號右邊的就是右值。左值和右值都是針對表示式而言的,左值是指表示式結束後依然存在的持久物...