在 C 中将参数传递给 lambda

新手上路,请多包涵

我似乎错过了 C++ 中 lambda 机制的一些要点。这是代码:

 std::vector<int> vec (5);

int init = 0;
std::generate(begin(vec), end(vec), [init]() mutable { return ++init; });

for (auto item : vec) {
    std::cout << item << " ";
}
std::cout << std::endl << init << std::endl;

如果没有 mutable 它不会编译,因为我在 lambda 中更改了 init

现在,据我了解,为每个向量的项目调用 lambda,并使用 init新副本,即 0。因此,每次都必须返回 1。但是这段代码的输出是:

1 2 3 4 5

0

看起来 generate 通过副本捕获 init 在其执行开始时 只捕获一次。但为什么?它应该像这样工作吗?

原文由 IgorStack 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 587
2 个回答

现在,据我所知,每个向量的项目都会调用 lambda,并使用一个新的 init 副本(即 0)。

这是不正确的。 lambda 只是另一种创建类并为其提供 operator() 的方式。 lambda 的 [] 部分描述了成员变量以及它们是通过引用还是通过值捕获的。 lambda 的 () 部分是 --- 的参数列表,而 operator() {} 部分是该函数的主体。 mutable 部分告诉编译器使 operator()const 因为它是 const 默认为 —a375b3418f43cf8e7a8

所以

[init]() mutable { return ++init; }

变成

struct compiler_generated_name
{
    int init; // we captured by value

    auto operator()() // since we used mutable this is non const
    {
        return ++init;
    }
};

为了简洁起见,我在这里使用了一个结构,但 lambda 被指定为类类型,因此可以使用 class

这意味着 init init 与上一次迭代中的 --- 相同,因为您只捕获一次。记住这一点很重要

auto generate_lambda()
{
    int foo = 0;
    return [&foo](){ return ++foo; };
}

当函数返回并使用它是未定义的行为时,将为您留下对 foo 的悬空引用。

原文由 NathanOliver 发布,翻译遵循 CC BY-SA 3.0 许可协议

lambda 是编译器生成的结构,等效于:

 struct lambda
{
    int init = 0; // captured value

    auto operator()() // non-const, due to `mutable`
    {
        return ++init;
    }
};

因此, init 仅在 lambda 中被捕获和复制一次 - 多次调用 lambda 不会再次捕获 init

原文由 Vittorio Romeo 发布,翻译遵循 CC BY-SA 3.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题