bas*_*eln 6 c++ lambda memory-management c++11
当我通过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 health\n";
} else {
std::cout << "doesn't have enough health\n";
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是输出:
MyClass created!
MyClass destroyed!
5
has enough health
Run Code Online (Sandbox Code Playgroud)
tem*_*def 18
根据cppreference.com网站的lambda函数文档
悬挂参考文献
如果通过引用(隐式或显式)捕获实体,并且在实体的生存期结束后调用闭包对象的函数调用操作符,则会发生未定义的行为.C++闭包不会延长捕获的引用的生命周期.
换句话说,您通过引用捕获对象然后让对象的生命周期结束这一事实意味着调用lambda会导致未定义的行为.由于UB可能起作用的一种可能方式是"即使对象已经死亡,该对象看起来仍然存活且很好",我怀疑你看到未定义的行为表现为没有出现任何错误.
我怀疑如果编译器为临时变量分配了唯一的堆栈位置,情况就是这样.这意味着在对象的生命周期结束之后,在main返回之前,内存不会被任何东西触及.因此,你会看到变量保持该值5,就像之前一样,因为没有别的东西写在它上面.
希望这可以帮助!