使用初始化捕獲來把物件移動到閉包

2021-08-07 12:56:56 字數 2094 閱讀 6493

但那是c++11,c++14就不一樣啦,它直接支援將物件移動到閉包。如果你的編譯器支援c++14,歡呼吧,然後繼續讀下去。如果你依然使用c++11的編譯器,你還是應該歡呼和繼續讀下去,因為c++11有接近移動捕獲行為的辦法。

缺少移動捕獲被認為是c++11的乙個缺陷,最直接的補救方法是在c++14中加上它,但標準委員會採用了另外一種方法。它們提出了一種新的、十分靈活的捕獲技術,引用捕獲只是屬於這種技術的其中一種把戲。這種新能力被稱為初始化捕獲(init capture),實際上,它可以做c++11捕獲格式能做的所有事情,而且更多。初始化捕獲不能表示的是預設捕獲模式,不過條款31解釋過無論如何你都應該遠離預設捕獲模式。(對於將c++11捕獲轉換為初始化捕獲的情況,初始化捕獲的語法會比較囉嗦,所以如果c++11捕獲能解決問題的情況下,最好使用c++11捕獲。)

使用初始化捕獲讓你有可能指定

成員變數的名字(留意,這是閉包類的成員變數,這個閉包類由lambda生成)和 (初始化那成員變數的)表示式 。

這裡是如何使用初始化捕獲來把std::unique_ptr移動到閉包內:?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

classwidget ;

auto pw = std::make_unique();//建立widget

...// 配置*pw

auto func = [pw = std::move(pw)]// 以std::move(pw)來初始化閉包中成員變數pw

初始化捕獲的**部分是pw = std::move(pw),「=」左邊的是你指定的閉包類的成員變數名,右邊的是進行初始化表示式。有趣的是,「=」左邊的作用域和右邊的作用域不同,左邊的作用域是在閉包類內,而右邊的作用域和lambda被定義的地方的作用域相同。在上面的例子中,「=」左邊的名字pw指的是閉包類的成員變數,而右邊的名字pw指的是在lambda之前宣告的物件,即由make_unique建立的物件。所以pw = std::move(pw)的意思是:在閉包中建立乙個成員變數pw,然後用——對區域性變數pw使用std::move的——結果初始化那個成員變數。

通常,lambda體內**的作用域在閉包類內,所以**中的pw指的是閉包類的成員變數。

在上面例子中,注釋「配置*pw」表明了在std::make_unique建立widget之後,在lambda捕獲指向widget的std::unique_ptr之前,widget在某些方面會被修改。如果這個配置不是必需的,即,如果std::make_unique建立的widget物件的狀態已經適合被lambda捕獲,那麼區域性變數pw是不必要的,因為閉包類的成員變數可以直接被std::make_unique初始化:?

12

auto func = [pw = std::make_unique()]// 以呼叫make_unique的結果

;// 來初始化閉包的區域性變數pw

這應該清楚地表明在c++14中,c++11的「捕獲」概念得到顯著推廣,因為在c++11,不可能捕獲乙個表示式的結果。因此,初始化捕獲的另乙個名字是generalized lambda capture(廣義lambda捕獲?)。

c 使用初始化列表來初始化字段

includeusing namespace std class student1 student1 int i b i a b 異常順序 發現a的值為0 b的值為2 說明初始化僅僅對b有效果,對a沒有起到初始化作用 student1 int a,int b a a b b 正常順序 發現a b 2...

確定物件使用前已經初始化

一 中心內容 1 為內建型別物件進行手工初始化,因為c 不保證初始化他們。2 建構函式最好使用成員初始列表,而不要在建構函式本體內使用賦值操作。初始列表列出的成員變數,其排列次序應該和它們在class中的宣告次序相同 3 為免除 跨編譯單元值初始化次序 問題,請以local static物件替換no...

4 確定物件在使用前已被初始化

一 盡量使用成員初始化的方式初始化成員 c 規定成員初始化發生早於建構函式,建構函式最好使用成員初值列,而不要在建構函式中使用賦值操作。初值列中的成員變數的初始化順序是根據這些成員變數宣告的順序進行初始化的,所以為了保證一致性,成員初值列中的順序最好跟宣告順序一致。二 為避免 跨編譯單元的初始化先後...