为此得到一个boost :: shared_ptr


76

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

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

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

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

这使我想到了一个问题:是否存在任何标准模式来从这些对象之一的方法内部获取您知道的现有共享指针的副本?使用介入式引用是我唯一的选择吗?


在这里使用介入式引用计数是我唯一的选择吗? ”该选项出了什么问题?
curiousguy 2011年

也许什么都没有。取决于您的情况。它的确会使您的对象变大,并且可能无法在您无法控制要保存智能指针的类的地方工作。
乔·路德维希

enabe_shared_from_this现在在中std::。看看我的答案。
约翰·隆德伯格

Answers:


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()时,这是一个好主意。它将确保不释放对象。


f()就像“ .Copy()”一样,它也是一个浅表副本。
安东·安德列夫

19

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

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


1
同意 您可以多次使用foo(const Object * object_ptr){} foo(obj.get()); 其中obj是boost :: shared_ptr <Object>。在网上搜索Herb Sutter,是另一篇文章作家,他对此和类似问题有很多了解。
十亿

1
这一点意义不大,但是...如果可以使用指针,则(很可能)可以使用引用,这是更好的IMO。
denis-bu 2013年

1
@ denis-bu,除非NULL有可能使用指针。但是你说的很好。
Mark Ransom 2013年

显然这晚了12年,但我不明白这个答案。bar的参数类型与原始指针不同。如果没有“ explicit”关键字使传递“ this”无法编译,编译器将不会尝试从原始指针构造shared_ptr,在进程中创建引用计数块,将引用计数设置为1,然后打开从栏退出,将引用计数减为0,然后尝试删除“ this”?
福斯特·邦多格

1
@FosterBoondoggle我的建议是将参数类型更改bar为原始指针。
Mark Ransom



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';

3

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

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

编辑:糟糕,我稍微看错了问题,现在我看到此答案不能完全解决问题。无论如何,我都会把它保留下来,以防这对从事类似代码工作的人有所帮助。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.