根据我的经验,似乎要么:
- 在函数调用中创建的 lambda 表达式在调用后立即销毁
- 调用需要
std::function
的函数会从 lambda 中创建一个临时对象 (std::function),并且该对象在调用后销毁
可以通过以下代码片段观察到此行为:
const function<void()>* pointer;
void a(const function<void()> & f)
{
pointer = &f;
}
void b()
{
(*pointer)();
}
int main()
{
int value = 1;
std::cout << &value << std::endl;
// 1: this works
function<void()> f = [&] () { std::cout << &value << std::endl; };
a(f);
// 2: this doesn't
a([&] () { std::cout << &value << std::endl; });
/* modify the stack*/
char data[1024];
for (int i = 0; i < 1024; i++)
data[i] = i % 4;
b();
return 0;
}
第二种情况到底发生了什么?
是否有一种正确的方法来调用 a()
而无需创建显式 std::function
对象?
编辑:: 这两个版本(1 和 2)都可以正确编译,但会产生不同的输出:
版本 1:
0x7fffa70148c8
0x7fffa70148c8
版本 2:
0x7fffa70148c8
0
最佳答案
如果你创建一个临时文件,它会在行尾消失。正如您正确指出的那样,这意味着存储指向它的指针是一个坏主意。
如果你想存储一个指向std::function
(或其他任何东西)的指针,你需要确保它的生命周期在你停止使用指针之前不会结束。这意味着您确实需要 std::function
类型的命名对象。
关于第二种情况发生的情况:您创建了一个临时 lambda 以传递给该函数。由于该函数需要一个 std::function
,因此将从 lambda 创建一个临时的 std::function
。这两个都将在该行的末尾被销毁。因此,您现在有一个指向已销毁的临时对象的指针,这意味着尝试使用指向的对象将使您牢牢地进入未定义的行为领域。
关于lambda 对象的 C++ 地址作为函数的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13788590/