2015-12-02 158 views
1

我想了解lambdas如何在C++中深入工作。我寫了下面這段代碼。用lambda調用移動構造函數

#include <iostream> 
#include <functional> 

struct A 
{ 
    A() { std::cout << "A" << (data = ++count) << ' '; } 
    A(const A& a) { std::cout << "cA" << (data = a.data + 20) << ' '; } 
    A(A&& a) { std::cout << "mA" << (data = std::move(a.data) + 10) << ' '; } 
    ~A() { std::cout << "dA" << data << ' '; } 
    int data; 
    static int count; 
}; 

int A::count = 0; 

void f(A& a, std::function<void(A)> f) 
{ 
    std::cout << "("; 
    f(a); 
    std::cout << ") "; 
} 

int main() 
{ 
    A temp, x; 
    auto fun = [=](A a) {std::cout << a.data << '|' << x.data << ' ';}; 
    std::cout << "| "; 
    f(temp, fun); 
    std::cout << "| "; 
} 

輸出如下。

A1 A2 cA22 | cA42 mA52 dA42(cA21 mA31 31 | 52 dA31 dA21)dA52 | DA22 DA2 DA1

這是很清楚,我,除了'MA52'移動構造函數調用。請注意,我通過值使用變量捕獲,因此如果沒有移動構造函數,則會在此處調用複製構造函數。爲什麼在這一步有額外的複製/移動?當fun被作爲參數傳遞給f時,人們會期望該對象僅被複制一次。此外,該對象的第一個副本立即銷燬。爲什麼?這是什麼中介副本?

回答

2

讓我們打電話給你的lambda類型L。它是未命名的,但是在沒有名字的情況下引用它會引起混淆。

構造函數std::function<void(A)>(L l)以值爲L。這涉及到創建原始fun的副本。

構造函數然後將lambda從l移動到由std::function<void(A)>包裝管理的某些存儲中。這一舉措還涉及移動任何被捕獲的實體。

1

std::function<void(A)>採用您傳遞給它的函數對象(這是您的輸出中的cA42)。然後它將函數對象移入其內部存儲器(這是mA52)。