2011-03-12 56 views
14

是否允許編譯器消除按值捕獲所需的副本C++ 0x:爲Lambda捕獲值,總是一個副本?

vector<Image> movie1; 
apply([=movie1](){ return movie1.size(); }); 
  • 是否有任何情況下,編譯器並不需要複製movie1
    • 也許如果編譯器可以知道,那apply實際上並不是更改movie1
    • 或者是否幫助Lambdas默認const仿函數在任何情況下?
  • 它是否幫助在所有vector轉移構造移動分配
    • 如果是,是否需要將這些添加到Image以防止昂貴的副本在這裏?
  • 有沒有在機制上的差異何時以及如何需要副本通過值捕獲相比按值參數?例如。 void operate(vector<Image> movie)

回答

9

我很確定它不能。

即使外層函數不再明確地使用該變量,移動該變量也會改變銷燬的語義。

移動構造函數爲Image沒有幫助,vector可以moveswap而不移動其元素。

如果變量從此處只讀爲正向,爲什麼不通過引用捕獲?你甚至可以創建一個const引用並捕獲它。

如果該變量不是隻讀的,則需要該副本。無論外函數還是lambda執行修改都無關緊要,編譯器不能允許該修改對另一個可見。

之間看到價值捕獲按值參數傳遞是捕獲而得名,它不能是一個臨時的唯一區別。因此不能使用傳遞適用於臨時對象的優化。

+0

「爲什麼不通過引用捕獲」?我正在理解所有的影響。我同意。 「唯一的區別......」是一個很好的答案。完善! – towi 2011-03-13 16:03:13

3

總是「as-if」規則。只要它看起來就好像規則一樣,編譯器可以做任何喜歡的事情。因此,對於複製構造函數和析構函數沒有副作用並且沒有對副本進行更改或者之後沒有訪問原始對象的對象(因此如果我們對該對象進行更改,沒有人會注意到),編譯器可以證明根據「如果」規則刪除該副本是合法的。正如@Ben所說,除此之外,不,它不能僅僅消除副本。 「常規」複製細則不包括這種情況。

+0

這就是我正在尋找的術語:* copy elision *。謝謝澄清,這些不能應用在這裏。謝謝。 – towi 2011-03-15 09:57:44

+0

複製elision在此處不適用,因爲在有效「移動」值的情況下(原始值不能再被訪問 - 對於複製初始化和返回值都是這樣),引入了複製elision。在lambda的情況下,您可以在lambda和原始上下文中訪問捕獲的值,因此它是一個真正的副本。 – Suma 2011-03-15 10:23:21