什么是C ++ lambdaexpression式的生命周期?

(我已经读过C ++中lambda派生的隐式函子的生命周期了 ,它并没有回答这个问题。)

我明白,C ++ lambda语法只是用一个调用操作符和某个状态来创build一个匿名类的实例,而我理解该状态的生命周期需求(由是否通过引用的值捕获来决定)。 lambda对象本身的生命周期? 在下面的例子中,返回的std::function实例是否有用?

 std::function<int(int)> meta_add(int x) { auto add = [x](int y) { return x + y; }; return add; } 

如果是,它是如何工作的 ? 这似乎有点太神奇了 – 我只能想象它通过std::function复制我的整个实例,这可能是非常沉重取决于我所捕获的 – 在过去,我已经使用std::function主要与裸函数指针,并复制这些很快。 从std::function的types擦除来看,它也有问题。

如果你用一个手工轧制的仿函数replace你的lambda,生命就是这样:

 struct lambda { lambda(int x) : x(x) { } int operator ()(int y) { return x + y; } private: int x; }; std::function<int(int)> meta_add(int x) { lambda add(x); return add; } 

该对象将被创build,在meta_add函数中是本地的,然后[包括x的值在内]移动到返回值中,然后本地实例将超出范围并被正常销毁。 但是从函数返回的对象只要保存它的std::function对象就会保持有效。 这显然取决于调用上下文多长时间。

看来你对std::function比lambdas更困惑。

std::function使用了一种称为type-erasure的技术。 这是一个快速的飞行。

 class Base { virtual ~Base() {} virtual int call( float ) =0; }; template< typename T> class Eraser : public Base { public: Eraser( T t ) : m_t(t) { } virtual int call( float f ) override { return m_t(f); } private: T m_t; }; class Erased { public: template<typename T> Erased( T t ) : m_erased( new Eraser<T>(t) ) { } int do_call( float f ) { return m_erased->call( f ); } private: Base* m_erased; }; 

你为什么要删除这个types? 是不是我们想要的types只是int (*)(float)

擦除types允许Erased现在可以存储任何可调用的值,如int(float)

 int boring( float f); short interesting( double d ); struct Powerful { int operator() ( float ); }; Erased e_boring( &boring ); Erased e_interesting( &interesting ); Erased e_powerful( Powerful() ); Erased e_useful( []( float f ) { return 42; } ); 

这是:

 [x](int y) { return x + y; }; 

相当于:(或者也可以考虑)

 struct MyLambda { MyLambda(int x): x(x) {} int operator()(int y) const { return x + y; } private: int x; }; 

所以你的对象正在返回一个看起来就像这样的对象。 其中有一个定义良好的复制构造函数。 所以看起来非常合理,它可以正确地从一个函数中拷贝出来。

在你发布的代码中:

 std::function<int(int)> meta_add(int x) { auto add = [x](int y) { return x + y; }; return add; } 

std::function<int(int)>返回的std::function<int(int)>对象实际上包含已分配给局部variablesadd的lambda函数对象的移动实例。

当定义一个按值或按引用捕获的C ++ 11 lambda时,C ++编译器自动生成一个唯一的函数types,当lambda被调用或分配给一个variables时,它的一个实例被创build。 为了说明,你的C ++编译器可能为[x](int y) { return x + y; }定义的lambda生成以下类types[x](int y) { return x + y; } [x](int y) { return x + y; }

 class __lambda_373s27a { int x; public: __lambda_373s27a(int x_) : x(x_) { } int operator()(int y) const { return x + y; } }; 

然后, meta_add函数基本上等同于:

 std::function<int(int)> meta_add(int x) { __lambda_373s27a add = __lambda_373s27a(x); return add; } 

编辑:顺便说一句,我不知道如果你知道这一点,但这是一个函数在C ++ 11中的例子。