【问题标题】:Move constructor called with lambda移动用 lambda 调用的构造函数
【发布时间】:2016-03-06 14:48:06
【问题描述】:

我试图深入了解 lambda 在 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' 移动构造函数调用。请注意,我使用的是按值捕获变量,因此如果没有移动构造函数,将在此处调用复制构造函数。为什么在这一步有额外的复制/移动?当fun 作为参数传递给f 时,人们会期望该对象只被复制一次。此外,对象的第一个副本立即被销毁。为什么?这个中间副本是什么?

【问题讨论】:

    标签: c++ c++11 visual-c++ lambda move-semantics


    【解决方案1】:

    我们将您的 lambda 类型称为 L。它没有命名,但不命名会让人感到困惑。

    构造函数std::function&lt;void(A)&gt;(L l) 采用L 的值。这涉及创建原始fun 的副本。

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

    【讨论】:

      【解决方案2】:

      std::function&lt;void(A)&gt; 获取您通过值传递给它的函数对象(这是您输出中的 cA42)。然后它将函数对象移动到其内部存储器(这是 mA52)。

      【讨论】:

        猜你喜欢
        • 2011-05-22
        • 2017-07-03
        • 2015-06-27
        • 2017-11-03
        • 2015-02-21
        • 2016-03-28
        • 2019-05-27
        • 2012-10-19
        • 1970-01-01
        相关资源
        最近更新 更多