我不会假装我对lambdas非常有经验,但是对于这个看似简单的问题,我认为我需要更深入地了解它是如何运作的。
我在外部作用域上实例化一个对象,并使用2个lambdas,我尝试修改该指针。
// Object to be manipulated
Object* obj= nullptr;
// To be invoked externally in order to construct and initialize obj
std::function<void(std::function<void(const String&)>)> SetObject
= [&obj](std::function<void(const String&)> func)
{
obj= new Object();
// ... Initialize Values
};
// To be invoked externally to reset and delete obj
std::function<void()> ResetObject
= [&obj]()
{
if(obj)
{
delete obj;
obj= nullptr;
}
};
在创建Object的新实例之前,主代码会执行并首先调用 RESET 方法。假设&#34;主要&#34;代码无法访问,读取或修改obj - 因此依赖于盲目重置。
预期结果:第一次调用重置表达式时,对obj的检查应返回false,因为obj在外部作用域中设置为nullptr - 没有任何反应。
实际结果:执行重置时,obj不再指向NULL,检查返回true并调用delete,导致访问冲突。
我想知道我试图做的是一个无效的操作,或者我捕获变量的方式是否不正确。我尝试按值捕获指针,将函数设置为可变,以及绝望的参考和值捕获的组合。
编辑:此时,我认为对象的范围是其他人指出的主要罪魁祸首。我将尝试解决方法 记住并报告回来。
答案 0 :(得分:1)
虽然我们无法单独从您的示例中看出,但我怀疑obj
可能是一个局部变量,在被捕获后超出了范围。解决这个问题的一种方法是添加另一个间接级别:
Object** objptr = new Object*();
std::function<void(std::function<void(const String&)>)> SetObject
= [objptr](std::function<void(const String&)> func)
{
*objptr = new Object();
};
std::function<void()> ResetObject
= [objptr]() // Note we are now capturing objptr by value
{
if(*objptr)
{
delete *objptr;
*objptr = nullptr;
}
// Is objptr reused by another call to SetObject?
// If not, delete it here as well.
// delete objptr;
};