调用指向已销毁Lambda的指针是否合法?含带捕获Lambda的通用场景
调用指向已超出作用域Lambda的指针是否合法?
无捕获Lambda的情况
你的示例代码中使用的是无捕获的Lambda,这种情况是合法的。
C++标准规定,无捕获的Lambda可以隐式转换为同签名的普通函数指针。这类Lambda的函数体本质上是全局可见的代码片段,和普通全局函数的存储方式类似——即使Lambda变量(lambda)超出作用域被销毁,函数指针(fun)指向的代码依然存在且有效。所以调用fun(6)是完全合规的,不会触发未定义行为。
带捕获Lambda的情况
如果是带有捕获的Lambda,情况就完全不同了:
- 带捕获的Lambda无法隐式转换为普通函数指针,因为它的行为依赖于捕获的变量(闭包状态),必须通过闭包对象来调用其
operator()成员函数。 - 若你持有指向闭包对象的指针/引用,当闭包对象(即Lambda变量)超出作用域被销毁后,这个指针就变成了悬垂指针。此时通过该指针调用Lambda的行为属于未定义行为——无论捕获的是值还是引用:
- 即使是值捕获,闭包对象销毁后,其内部存储的捕获值也会被释放,访问已销毁对象的成员函数会导致不可预料的结果;
- 引用捕获的话,捕获的外部变量本身已经超出作用域,调用Lambda时访问该引用同样是未定义行为。
示例说明(带捕获Lambda的非法场景)
#include <iostream> #include <functional> int main() { std::function<int(int)> fun; int* lambda_ptr = nullptr; { int x = 10; auto lambda = [x](int a)->int{std::cout << a + x << std::endl; return a + x;}; fun = lambda; // std::function保存闭包对象拷贝,后续调用合法 lambda_ptr = reinterpret_cast<int*>(&lambda); // 指向闭包对象的指针 } // 若通过lambda_ptr调用原Lambda,属于访问已销毁对象,是未定义行为 }
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

