2013-01-23 49 views
2

我有一個簡單的代碼:LAMBDA捕獲列表和複製

#include <iostream> 
#include <functional> 

struct Copy 
{ 
    Copy(){} 
    Copy(const Copy&) 
    { 
     std::cout << "Copied!\n"; 
    } 
}; 

int main() 
{ 
    Copy copy; 
    std::function<void()> func = [=]{(void)copy;}; 
    return 0; 
} 

而且它調用拷貝構造函數2次,我想把它只有一次。我知道我可以在這個簡化的例子中使用auto,但是我需要將它存儲以備稍後使用,所以auto不是選項。 而我的問題:有沒有一種方法來存儲lambda =捕獲列表,並只有一個捕獲的對象的副本?

+0

我很驚訝的情況下被複制,爲您塑造功能實際上並沒有被調用。你使用什麼編譯器和版本? –

+0

@JoachimPileborg:當然有兩個副本:一個將'copy'複製到lambda中,另一個將lambda(具有'Copy'成員)複製到'std :: function'中。 – Mankarse

回答

4

有兩個副本:一個將copy複製到lambda中,另一個發生在將lambda(具有Copy成員)複製到std::function時發生。

如果你想要一個副本,一個舉動,你將需要使Copy對象是可移動的:

#include <iostream> 
#include <functional> 

struct Copy 
{ 
    Copy(){} 
    Copy(const Copy&) 
    { 
     std::cout << "Copied!\n"; 
    } 
    Copy(Copy&&) 
    { 
     std::cout << "Moved!\n"; 
    } 
}; 
//Prints: 
//Copied! 
//Moved! 
int main() 
{ 
    Copy copy; 
    std::function<void()> func = [=]{(void)copy;}; 
    return 0; 
} 
+0

這是移動的標準?我的意思是lambda必須有move-ctor/operator =? – ixSci

+0

@ixSci:是的 - 參見'[expr.prim.lambda]/19':「與lambda表達式相關的閉包類型有一個刪除的(8.4.3)默認構造函數和一個刪除的拷貝賦值操作符。隱式聲明的拷貝構造函數(12.8),並且可能有一個隱式聲明的移動構造函數(12.8)[注意:拷貝/移動構造函數隱式定義的方式與其他隱式聲明的拷貝/移動構造函數隱式定義的方式相同。 - 結束註釋]「。 (感謝您的詢問,關於'mutable'的提示是錯誤的) – Mankarse

+0

謝謝Mankarse!不過,我可能會被「可能有一個隱含聲明的移動構造函數」所困惑。 GCC和Clang擁有它,而MSVC則沒有。我不知道我可以提交錯誤,因爲這種行爲不是由標準強制的,但只是「未被禁止」 – ixSci