c ++闭包创建

Lin*_*Lin 9 c++ lambda closures c++11 c++14

#include <iostream>
#include <algorithm>
#include <vector>

int main()
{
  // Block 1
  {
    auto inc = []() { int i = 0; return [&]() { return i++; }; }();
    std::vector<int> v(10, 10);
    std::generate(v.begin(), v.end(), inc);
    for (auto i : v) std::cout << i << std::endl;
  }

  // Block 2
  {
    auto inc = []() { int i = 0; return [&]() { return i++; }; };
    std::vector<int> v(10, 10);
    std::generate(v.begin(), v.end(), inc());
    for (auto i : v) std::cout << i << std::endl;
  }
}
Run Code Online (Sandbox Code Playgroud)

我不确定为什么这两个块会产生不同的结果.

Block 1: 32767 ... 32776
Block 2: 0 ... 10
Run Code Online (Sandbox Code Playgroud)

并且因为std::generategenerator(inc)是按值传递的,所以我认为它应该没问题,对吧?

我正在运行OS X.

谢谢,


请注意,上述代码的结果未定义,请参见下文.

Bar*_*rry 10

我不确定为什么这两个块会产生不同的结果.

两者都是未定义的行为,所以这个问题没有实际意义.在任何一种情况下,我们都有一个lambda:

auto f = []() { int i = 0; return [&]() { return i++; }; };
Run Code Online (Sandbox Code Playgroud)

f()返回一个具有悬空引用的lambda:i在调用结束时被销毁f.悬挂引用发生无关紧要- 无论是在generate()通话之前还是在generate()通话中发生的.

如果你想用lambda创建一个生成计数器,直接的方法是使lambda变为可变并使用init-capture:

auto inc = [i=0]() mutable { return i++; };
Run Code Online (Sandbox Code Playgroud)

mutable是必需的,因为lambdas是const默认的,我们需要直接修改成员i.


以上是C++ 14(由于通用的init-capture).我们可以通过简单地改变嵌套的lambda结构从内部lambda引用捕获到按值捕获来在C++ 11中完成这项工作:

auto inc = []{ int i = 0; return [=]() mutable { return i++; }; }();
//                               ~~~   ~~~~~~~
Run Code Online (Sandbox Code Playgroud)

那是......有点讨厌,但它有效吗?