boost smart_ptr 库包含两种类型,使类能够为自己提供shared_ptrs,enable_shared_from_this(也可用于 stl 的智能指针)和enable_shared_from_raw。对我来说,后者似乎更优越,因为它允许在构造函数中创建共享指针。但是,文档中根本没有提到这个类,不是根 boost/标头的一部分,谷歌搜索它主要在实际的 .hpp 文件中给出命中。
boost::enable_shared_from_raw 是否已弃用或以其他方式不适合使用?我错过了什么吗?
enable_shared_from_raw
的问题在于它很危险;你可能会无意中泄漏物体。
如果在调用 shared_from_raw
时未授予指向 shared_ptr
实例的原始指针的所有权,则 enable_shared_from_raw
基类将保留对自身的强引用,直到您这样做为止。
只要它保留对自身的强引用,在手动删除对象之前,引用计数将无法达到 0,这完全消除了使用 shared_ptr
的所有好处。一旦某些东西获得了原始指针的所有权,它就会将其强引用降级为弱引用,一切都很好。
class object : boost::enable_shared_from_raw { }
// Leak! When shared_from_raw is called, raw takes ownership of itself.
object* raw = new object;
boost::shared_ptr<object> bar = boost::shared_from_raw(raw);
// This is fine; bar already owns the object when shared_from_raw is invoked.
object* raw = new object;
boost::shared_ptr<object> bar(raw);
boost::shared_ptr<object> foo = boost::shared_from_raw(raw);
// Also fine; ownership is transferred to bar.
object* raw = new object;
boost::shared_ptr<object> foo = boost::shared_from_raw(raw);
boost::shared_ptr<object> bar(raw);
// Still a leak! Nothing external has taken ownership of the raw pointer.
object* raw = new object;
boost::shared_ptr<object> bar = boost::shared_from_raw(raw);
boost::shared_ptr<object> foo = bar;
我认为你想要在构造函数中调用shared_from_this()
的最常见情况是你想用某种管理器注册对象;这很可能导致这里描述的泄漏。
// This use case results in a leak.
// Nothing external takes ownership of the raw pointer.
struct Object;
struct ObjectManager
{
void RegisterObject(boost::shared_ptr<Object> obj)
{
m_objects.push_back(obj);
}
std::list<boost::shared_ptr<Object> > m_objects;
};
static ObjectManager gObjectManager;
struct Object : boost::enable_shared_from_raw
{
Object()
{
gObjectManager.RegisterObject(boost::shared_from_raw(this));
}
}
enable_shared_from_this
设置了额外的限制来防止这种类型的泄漏。