我不明白 lambda 是如何 move 的。考虑以下代码:
#include <iostream>
#include <utility>
#include <string>
struct Foo // non-copyable type
{
Foo() = default;
Foo(const Foo&) = delete; // cannot copy
Foo(Foo&&) = default; // can move
};
auto lambda = [p = Foo()](){
std::string x{"lambda"};
std::cout << x << std::endl;
};
// auto copied_lambda = lambda; // cannot copy due to Foo non-copyable init capture
auto moved_lambda = std::move(lambda); // we moved it
struct Functor // "simulate" a lambda
{
std::string x{"functor"};
void operator()() const
{
std::cout << x << std::endl;
}
};
Functor functor; // initial functor object
auto moved_functor = std::move(functor); // moved it
int main()
{
lambda(); // why does it display "lambda" since it was moved?
moved_lambda(); // displays "lambda", was moved in, everything OK
functor(); // doesn't display "functor", was moved
moved_functor(); // displays "functor", was moved in, everything OK
}
如您所见,我声明了一个 Foo
我传递给 lambda
的初始化捕获的不可复制类(但可 move ) , 所以 lambda
最终只能 move 。 lambda 闭包声明一个 std::string
(这是可 move 的)。接下来我 move lambda
进入moved_lambda
,所以我期待 std::string
也被 move 。但是,当我调用 lambda()
时在 main()
, 它仍然显示旧字符串,就好像它根本没有 move 一样。
然后我用仿函数“模拟”了 lambda,并且在 move 时 functor
进入moved_functor
, 初始 string
在 functor
也被 move 了,所以当我尝试在 main()
中显示它时我得到一个空字符串。我对这种行为感到困惑,为什么会出现这种不一致?我原以为 move 的 lambda(在内部只是一个函数对象)会 move 其组件而不是复制它们。我唯一的解释是 lambda
中的局部变量是const
,所以我们复制它们而不是 move 它们,但我不确定。是这样吗?
最佳答案
您的示例并不相同。对 lambda 的正确模拟是:
struct Functor // "simulate" a lambda
{
void operator()() const
{
std::string x{"functor"};
std::cout << x << std::endl;
}
};
请注意,x
现在位于函数内部。这两个示例现在的行为相同:即使它们被 move 了,它们也都打印了它们的局部变量。
解释很简单:内部变量不会被复制或 move ,因为它们在仿函数/lambda 被复制或 move 时不存在。当它们的 operator()
被调用时,它们会被创建和销毁。
关于c++ - lambda 是如何 move 的?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29852413/