为此获得boost :: shared_ptr

时间:2008-09-26 22:42:43

标签: c++ boost

我在代码中广泛使用boost:shared_ptr。实际上,堆上分配的大多数对象都由shared_ptr保存。不幸的是,这意味着我无法将this传递给任何需要shared_ptr的函数。请考虑以下代码:

void bar(boost::shared_ptr<Foo> pFoo)
{
    ...
}

void Foo::someFunction()
{
    bar(this);
}

这里有两个问题。首先,这不会编译,因为shared_ptr的T *构造函数是显式的。其次,如果我强制它使用bar(boost::shared_ptr<Foo>(this))构建,我将创建第二个指向我的对象的共享指针,最终会导致双重删除。

这让我想到了一个问题:是否有任何标准模式可以从其中一个对象的方法中获取您知道的现有共享指针的副本?使用侵入式引用计数是我唯一的选择吗?

6 个答案:

答案 0 :(得分:102)

您可以从enable_shared_from_this派生,然后您可以使用“shared_from_this()”代替“this”来生成指向您自己的自我对象的共享指针。

链接中的示例:

#include <boost/enable_shared_from_this.hpp>

class Y: public boost::enable_shared_from_this<Y>
{
public:

    shared_ptr<Y> f()
    {
        return shared_from_this();
    }
}

int main()
{
    shared_ptr<Y> p(new Y);
    shared_ptr<Y> q = p->f();
    assert(p == q);
    assert(!(p < q || q < p)); // p and q must share ownership
}

从成员函数生成线程到boost :: bind到shared_from_this()而不是这个时,这是一个好主意。它将确保不释放对象。

答案 1 :(得分:19)

只需使用函数参数的原始指针而不是shared_ptr。智能指针的目的是控制对象的生命周期,但C ++作用域规则已经保证了对象的生命周期:它至少与函数结束一样长。也就是说,调用代码不能在函数返回之前删除对象;因此,只要您不尝试删除函数内的对象,就可以保证“哑”指针的安全。

您需要将shared_ptr传递给函数的唯一时间是您希望将对象的所有权传递给函数,或者希望函数复制指针。

答案 2 :(得分:14)

boost有针对此用例的解决方案,请检查enable_shared_from_this

答案 3 :(得分:9)

你真的在酒吧内制作更多pFoo的共享副本吗?如果你内心没有做任何疯狂的事情,那就这样做:


void bar(Foo &foo)
{
    // ...
}

答案 4 :(得分:5)

使用C ++ 11 shared_ptrenable_shared_from_this现在位于标准库中。顾名思义,后者正好适用于这种情况。

http://en.cppreference.com/w/cpp/memory/shared_ptr

http://en.cppreference.com/w/cpp/memory/enable_shared_from_this

示例基于以上链接中的内容:

struct Good: std::enable_shared_from_this<Good>{
    std::shared_ptr<Good> getptr() {
        return shared_from_this();
    }
};

使用:

std::shared_ptr<Good> gp1(new Good);
std::shared_ptr<Good> gp2 = gp1->getptr();
std::cout << "gp2.use_count() = " << gp2.use_count() << '\n';

答案 5 :(得分:3)

接受指针的函数想要执行以下两种行为之一:

  • 拥有传入的对象,并在超出范围时将其删除。在这种情况下,您可以只接受X *并立即将scoped_ptr包装在该对象周围(在函数体中)。这将接受“this”,或者通常是任何堆分配的对象。
  • 将一个指针(不拥有它)分享给传入的对象。在这种情况下,根本不想使用scoped_ptr,因为你不希望删除函数末尾的对象。在这种情况下,你理论上想要的是shared_ptr(我在其他地方看到它被称为linked_ptr)。 boost库有a version of shared_ptr,这也是Scott Meyers的Effective C ++书籍(第3版第18项)中的推荐。

编辑:哎呀我稍微误解了这个问题,现在我看到这个答案并没有完全解决这个问题。无论如何,我会留下它,以防这对可能对类似代码工作的人有所帮助。