移动用 lambda 调用的构造函数
Move constructor called with lambda
我想深入了解 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' 移动构造函数调用。请注意,我使用的是按值捕获变量,因此如果没有移动构造函数,将在此处调用复制构造函数。为什么这一步多了一个copy/move?当 fun
作为参数按值传递给 f
时,人们会期望对象只被复制一次。此外,对象的第一个副本会立即被销毁。为什么?这个中间副本是什么?
我们称您的 lambda 类型为 L
。它没有命名,但在没有名字的情况下引用它会让人感到困惑。
构造函数 std::function<void(A)>(L l)
按值获取 L
。这涉及创建原始副本 fun
.
构造函数然后将 lambda 从 l
移动到由 std::function<void(A)>
包装器管理的某个存储中。该移动还涉及移动任何捕获的实体。
std::function<void(A)>
按值获取您传递给它的函数对象(这是输出中的 cA42)。然后它将函数对象移动到其内部存储(这是 mA52)。
我想深入了解 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' 移动构造函数调用。请注意,我使用的是按值捕获变量,因此如果没有移动构造函数,将在此处调用复制构造函数。为什么这一步多了一个copy/move?当 fun
作为参数按值传递给 f
时,人们会期望对象只被复制一次。此外,对象的第一个副本会立即被销毁。为什么?这个中间副本是什么?
我们称您的 lambda 类型为 L
。它没有命名,但在没有名字的情况下引用它会让人感到困惑。
构造函数 std::function<void(A)>(L l)
按值获取 L
。这涉及创建原始副本 fun
.
构造函数然后将 lambda 从 l
移动到由 std::function<void(A)>
包装器管理的某个存储中。该移动还涉及移动任何捕获的实体。
std::function<void(A)>
按值获取您传递给它的函数对象(这是输出中的 cA42)。然后它将函数对象移动到其内部存储(这是 mA52)。