这是C++ lambda 的寿命是否有限的后续问题?。
在我之前的问题中,尝试在 lambda 超出范围后使用它会导致崩溃。虽然这并不奇怪,但我认为我使用了 lambda 存储位置的错误思维模型,这让我认为它永远存在,即使它超出了范围。
也许是因为我经常使用微控制器,其中代码从非易失性闪存执行,这与数据存储器(例如堆栈)完全分开。但我想象创建 lambda 相当于显式编写一个独立函数,但语法更方便。IE:
void SaySomething()
{
cout << "Hello" << endl;
}
int main()
{
AcceptFunction([](){cout << "Hello" << endl;}); // I thought that this
AcceptFunction(SaySomething); // was the same as this
}
Run Code Online (Sandbox Code Playgroud)
我想象的是 lambda 编译为与其他非 lambda 代码一起静态存在的实际代码,并AcceptFunction传递一个指向该代码的指针。在这种情况下,该代码将始终存在于内存中,即使 lambda 超出范围也是如此。
但我的程序崩溃了,所以这不可能是真的。那么该代码在哪里?它在堆栈上吗?如果是这样,在具有闪存的架构(代码无法从堆栈中运行)上,行为是否会有所不同?
更新
请注意,这个问题是关于 lambda 的物理存储位置。我不希望行为有所不同,也不希望 lambda 的析构函数不被调用。
for*_*818 10
您关于 lambda 的心智模型太复杂了。请阅读此处,了解 lambda 表达式除了定义(未命名)仿函数类型并创建该类型的实例之外什么也不做。它不是魔法,而只是您可以手动编写的代码的简写。关于生命周期及其存储位置,与您可以自己编写的函子没有区别:
int main()
{
struct Hello {
void operator()() { std::cout << "Hello" << std::endl; }
};
AcceptFunction( Hello{} );
}
Run Code Online (Sandbox Code Playgroud)
定义一个类,Hello{}构造一个传递给 的临时实例AcceptFunction。临时变量在表达式末尾被销毁。
它的“物理存储”位置并不容易回答,因为编译器可能会完全优化实例并简单地内联std::cout << "Hello" << std::endl;在AcceptFunction. 然而,对于 lambda 来说,这与任何其他对象仍然没有本质上的不同。例如,当您调用时,foo(42)不一定42存储在任何地方。