2015-12-02 156 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)。