我遇到共享指针,lambda和范围的问题。
我的情况是我有一个我调用的方法,所以我可以稍后使用返回的值。这是正常的,直到这里。当我在这个方法中有一个异步方法时,问题出现了,我必须为shared_pointer做一组异常。我正在使用lambda函数来处理来自此异步方法的回调。在这个lambda中,我必须使用我的shared_pointer并在其上设置一个异常(来自其类的方法)resultPtr-> setException();
我首先使用了shared_ptr,然后是lambda中的weak_ptr(因为我在某些地方读过shared_ptr可能会导致内存泄漏)。但直到现在我想我真的需要使用shared_ptr。
我必须测试是否在第二个.cpp中设置了此异常,因此我调用该方法并使用返回的值。我把线程等了大约500ms然后我测试它是否有例外,但它没有。但是,在极少数情况下,它“hasException”。我可以看到lambda被调用,它通过我的日志设置异常,但它似乎没有改变我先返回的值(就像它指向不同的地方)。
我提到的第一种方法的输入对我的情况并不重要,只是它们是指针。
就我而言,我有类似的东西:
file1.cpp
typedef shared_ptr<Result> ResultPtr;
ResultPtr method_name(TypePtr args)
{
if(args != nullptr)
{
ResultPtr result = make_shared<Result>();
stuff->callAsync([this, result](input)
{
if(result == nullptr)
{
result->setException();
}
});
}
else
{
result->setError();
}
return result;
}
file2.cpp
bool testingMethod()
{
ResultPtr result = file1::methodName(TypePtr args)
std::this_thread::sleep_for(std::chrono::milliseconds(500));
test(result->hasException);
}
为了测试我正在使用另一个类,我用某些输入调用这个方法(这里不重要),我需要比较resultPtr的对象值。会发生的是,一旦它超出范围(返回a),我就无法再访问该对象了。在我调用此方法之后,我将线程等待大约1秒钟,但它永远不会更改状态(因为它不能指向被破坏的对象)
无论如何要克服这个?其他建议?
谢谢!
当然你不能再访问这个对象了,因为当destroyed离开shared pointer块的范围时它就是if(args)
,在那里创建了它。你需要让对象生活在方法之外,例如: G。将其存储为类成员或(
禁止!)在全局变量中。
是否需要将其包装在共享指针中尚不清楚,您需要提供一个MCVE以及更清晰的what you want to achieve描述。
如果你的callAsync
实际上是异步的,当局部变量result
和a
超出范围时,你的lambda可能会开始执行。您应该将所需的变量作为参数传递,例如与std::bind
绑定:
typedef shared_ptr<Result> ResultPtr;
ResultPtr method_name(args)
{
if(args)
{
ResultPtr a = make_shared<Result>();
std::weak_ptr<Result> result(a);
stuff->callAsync(std::bind([this](std::weak_ptr<Result> result_param)
{
auto resultPtr = result_param.lock();
if(resultPtr)
{
resultPtr->setValue()
...other stuff...
}
}, result));
}
else
{
a->setError();
}
return a;
}
是的,你的例子令人困惑
如果你需要lambda来保证它保持对象存活,为什么你使用弱指针传入,而不是共享指针?弱指针的目的是您所看到的行为,它本身不会使对象保持活动状态。
因为您只捕获一个弱指针,所以当唯一的共享指针超出范围时,如果它在锁定弱指针之前超出范围,则不会使共享指针保持活动状态。但是你可以捕获共享指针(通过值,因此获取副本)而不是使用弱指针。然后引用计数将递增,并且lambda中的共享指针将使其保持活动状态,并且只有当两个共享指针都超出范围时才会删除它。
像这样的共享所有权是共享指针的原因,如果希望在共享指针引用计数达到零时不再可访问该对象,则应该只使用弱指针。