c++ - lambda 是如何 move 的?

标签 c++ c++11 lambda c++14 move-semantics

我不明白 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 , 初始 stringfunctor也被 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/

相关文章:

c++ - 为什么这个虚函数调用如此昂贵?

c++ - 即使不知道元素的确切数量,也要调用 QVector::reserve 吗?

c++ - 为什么静态类类型函数返回零?

用于下载电子邮件的 C++ IMAP 库

c++ - 如何在 C++11 中检测一个类是否是最终的?

c++ - TR1 是 "missing"- 我的项目配置中缺少哪个 header 或库?

c++ - 结构操作,代码不起作用?

node.js - 无法在 Lambda 中创建具有 UTC 旁边时区的日期对象

c# - 为什么方法类型推断无法推断类型参数?

c# - 谓词参数在 C# 中如何在语法上起作用?