我正在考虑使用boost :: weak_ptr来实现一个对象池,这样当没有人使用其中一个对象时它们就会被收获。但我担心的是,它是一个多线程环境,似乎最后一个shared_ptr与一个超出范围的对象和一个从weak_ptr构造的新shared_ptr之间存在竞争条件。通常情况下,您可以通过锁定或其他方式保护此类操作;但是,这里的重点是你不知道shared_ptr何时可能超出范围。
我是否误解了关于boost :: shared_ptr和boost :: weak_ptr的事情?如果没有,是否有人对如何做有任何好的建议?
感谢。
安德鲁
答案 0 :(得分:11)
要使用weak_ptr
,您通常需要通过构建shared_ptr
来获取强引用。最后一步是原子的:您要么获得强引用,要么抛出bad_weak_ptr
异常。 (或者,在lock()
上调用weak_ptr
,然后获取强引用或null。)
示例(lock()
;足以适应其他风格):
void do_something(weak_ptr<foo> weak) {
// Grab strong reference
shared_ptr<foo> strong(weak.lock());
if (strong) {
// We now have a strong reference to use
} else {
// No strong references left; object already freed
}
}
答案 1 :(得分:3)
如果涉及线程安全,boost::weak_ptr
和boost::shared_ptr
都是相似的:如果存在对象将在某处被破坏的风险,则它们不是线程安全的。如果boost::shared_ptr
或weak_ptr中引用的对象在某处永久引用,则使用shared/weak
ptrs可以没有任何风险。
但是如果某些操作要取消引用对象的最后一个实例,那么那时你就不能对weak_ptr
进行一些操作了:特别是:你不能将weak_ptr
分配给另一个weak_ptr
因为它在内部使用shared_ptr
。此外,您不能使用锁定,因为结果是未定义的。此外,expired()
方法对于:它可能返回true是无效的,但是在代码的下一行,您的对象可能已经过期。
答案 2 :(得分:0)
是的,是的。在访问指针方面,Boost应该让一切安全;这是他们观点的一部分。
但是,如果您希望在最后一次shared_ptr退出之间以及想要创建下一个shared_ptr之间有延迟,那么您将获得一个空指针。 (如果你正确检查,你应该有一个适当的失败案例。)
但是你最终无法得到一个无效的shared_ptr