Lambda捕获和内存管理
Lambda Capture and Memory Management
当我在C++11 lambda中通过引用捕获对象,让该对象超出范围,然后执行lambda时,它仍然可以访问该对象。当我执行以下代码时,lambda调用仍然可以访问对象,尽管已经调用了析构函数!有人能解释一下为什么这有效,为什么我没有得到运行时错误吗?
#include <iostream>
class MyClass {
public:
int health = 5;
MyClass() {std::cout << "MyClass created!n";}
~MyClass() {std::cout << "MyClass destroyed!n";}
};
int main(int argc, const char * argv[])
{
std::function<bool (int)> checkHealth;
if(true) {
MyClass myVanishingObject;
checkHealth = [&myVanishingObject] (int minimumHealth) -> bool {
std::cout << myVanishingObject.health << std::endl;
return myVanishingObject.health >= minimumHealth;
};
} // myVanishingObject goes out of scope
// let's do something with the callback to test if myVanishingObject still exists.
if(checkHealth(4)) {
std::cout << "has enough healthn";
} else {
std::cout << "doesn't have enough healthn";
}
return 0;
}
这是输出:
MyClass created!
MyClass destroyed!
5
has enough health
根据cppreference.com网站关于lambda函数的文档
危险参考
如果通过引用(隐式或显式)捕获实体,并且在实体的生存期结束后调用闭包对象的函数调用运算符,则会发生未定义的行为。C++闭包不会延长捕获引用的生存期。
换句话说,您通过引用捕获了对象,然后让对象的生存期结束,这意味着调用lambda会导致未定义的行为。由于UB可能的一种工作方式是"即使对象已经死了,对象看起来仍然活着",我怀疑你看到的是未定义的行为,表现为没有出现任何问题。
我怀疑,如果编译器为临时变量分配了一个唯一的堆栈位置,就会出现这种情况。这意味着在对象的生存期结束后,在main
返回之前,内存不会被任何东西触及。因此,您会看到变量和以前一样保持值5
,因为它上面没有其他内容
希望这能有所帮助!
相关文章:
- 当vector是tje全局变量时,c++中vector的内存管理
- 我有一个线程 1:EXC_BAD_ACCESS(代码 = 1,地址 = 0x8)错误.我认为这是由于内存管理不好.我可以
- C++将字符串传递给 C 库以进行内存管理
- 从函数返回时C++内存管理
- 函数指针和 lambda 的内存管理
- 自定义内存管理器在发布模式下工作正常,但在调试模式下则不然
- C++中的内存管理
- C和C++中的内存管理有什么区别
- 字符 * 未从重载运算符或内存管理问题正确返回
- 如何在源代码中使用执行策略检测 C++17 的扩展内存管理算法的可用性?
- 底层指针和内存管理
- 智能指针,避免使用QNetworkAccessManager时进行手动内存管理
- c++中的内存管理问题
- 使用矢量时的内存管理
- 循环和内存管理中的指针算术C++?
- C++堆栈内存管理问题
- C 内存管理中的课程如何管理 - 研究
- 不可变数据模型的内存管理
- C++ 使用数组初始化时的 STL 向量内存管理
- SFML 纹理内存管理