以下的 C++ 代码会先打印 11.1
,然后导致崩溃。Lambda 函数在构造函数内部似乎被正确调用,但在稍后,同样的函数不再起作用!为什么会这样?Lambda 函数是否有有限的生命周期?
#include <functional>
#include <iostream>
class LambdaStore
{
public:
LambdaStore(const std::function<void(float)>& _fn)
: fn(_fn)
{
fn(11.1f);
}
void ExecuteStoredLambda()
{
fn(99.9f);
}
private:
const std::function<void(float)>& fn;
};
int main()
{
LambdaStore lambdaStore([](float a) { std::cout << a << '\n'; });
lambdaStore.ExecuteStoredLambda();
}
你没有存储一个 lambda 函数,而是存储了一个对 std::function
的引用。
实际上,当 lambda 隐式转换为 std::function
时,这个 std::function
会被创建为临时对象。这个 std::function
临时对象在构造函数被调用的行之后就会销毁。
LambdaStore(const std::function<void(float)>& _fn)
: fn(_fn)
{
fn(11.1f);
}
然而,即使你将类更改为直接通过模板使用 lambda 类型,lambda 本身也会在后续阶段销毁。但无论类型如何,这对于任何 C++ 类型都是成立的。以 int
为例:
class LambdaStore
{
public:
LambdaStore(const int& _i)
: i(_i)
{
std::cout << i;
}
void ExecuteStoredLambda()
{
std::cout << i;
}
private:
const int& i;
};
void main()
{
LambdaStore lambdaStore(1);
lambdaStore.ExecuteStoredLambda();
}
当绑定到函数参数时,临时对象不会在创建它们的语句之后获得生命周期延长。
然而,如果只使用花括号,它们会在直接绑定到成员引用时获得生命周期延长:
struct ref {
const int& i
};
int main() {
ref a{3};
std::cout << a.i;
ref b(3);
std::cout << b.i;
}
解决方案显然是将 std::function
存储为值,而不是引用:
class LambdaStore
{
public:
LambdaStore(const std::function<void(float)>& _fn)
: fn(_fn)
{
fn(11.1f);
}
void ExecuteStoredLambda()
{
fn(99.9f);
}
private:
std::function<
最后更新:2023年 8月 20日