使用lambda调用的Move构造函数

Move constructor called with lambda

本文关键字:Move 构造函数 调用 lambda 使用      更新时间:2023-10-16

我正在努力深入了解lambdas在C++中是如何工作的。我已经编写了以下代码。

#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'移动构造函数调用。请注意,我使用的是按值捕获变量,因此如果没有move构造函数,这里将调用copy构造函数。为什么在这一步需要额外的复制/移动?当fun作为参数通过值传递给f时,可以期望对象只复制一次。此外,对象的第一个副本会立即销毁。为什么?这个中间副本是什么?

让我们调用您的lambda类型L。它是未命名的,但在没有名字的情况下提及它会让人感到困惑。

构造函数std::function<void(A)>(L l)按值取L。这涉及到创建原始fun的副本。

然后,构造函数将lambda从l移动到由std::function<void(A)>包装器管理的某个存储中。此举还涉及移动任何被捕获的实体。

std::function<void(A)>按值获取传递给它的函数对象(这是输出中的cA42)。然后,它将功能对象移入其内部存储器(这就是mA52)。