在C++ 14中使用通用lambdas和自动返回类型功能获得的结果不同

Che*_*hen 5 c++ python lambda c++14

我试图用C++在python中实现这段高阶函数:

def add1(x):
    def helper():
        nonlocal x
        x += 1
        return x
    return helper
Run Code Online (Sandbox Code Playgroud)

以下是我创建的三个版本:

#include <iostream>
#include <functional>

using namespace std;

function<int(void)> add1_v1(int x) {
    function<int(void)> g = [&x]() {return ++x;};
    return g;
}

auto add1_v2(int x) {
    function<int(void)> g = [&x]() {return ++x;};
    return g;
}

auto add1_v3(int x) {
    auto g = [&x]() {return ++x;};
    return g;
}

int main() {
  auto a = add1_v1(100);
  auto b = add1_v2(100);
  auto c = add1_v3(100);
  for(int i = 0; i < 3; ++i) {
      cout << a() << endl;
  }
  cout << "-------------------------------------------" << endl;
  for(int i = 0; i < 3; ++i) {
      cout << b() << endl;
  }
  cout << "-------------------------------------------" << endl;
  for(int i = 0; i < 3; ++i) {
      cout << c() << endl;
  }
  return 0; 
}
Run Code Online (Sandbox Code Playgroud)

产出是:

101
102
103
-------------------------------------------
4239465
4239466
4239467
-------------------------------------------
4201325
4201325
4201325
Run Code Online (Sandbox Code Playgroud)

只有add1_v1符合我的要求.谁能解释一下我的原因?

Sam*_*hik 7

原因是这是未定义的行为.

内部lambda x通过引用捕获.

问题是,只要add()返回,它的参数就会被销毁,并且返回的lambda会有一个对被破坏对象的悬空引用.

lambda必须x按值捕获; 而你在我看来真正想做的是一个可变的lambda:

auto add(int x) {
    function<int(void)> g = [x]() mutable {return ++x;};
    return g;
}
Run Code Online (Sandbox Code Playgroud)

请注意,这种方法在随后复制返回的lambda时会带来某些影响; 但只要返回的lambda保持"在一个地方",在其剩余的生命周期中,所产生的语义可能就是你所期望的.