我有一个引用,想要调用一个带有boost :: shared_ptr的函数

时间:2012-01-25 15:16:24

标签: c++ reference shared-ptr

我有一个对象的引用,想要调用一个带有此对象的boost :: shared_ptr的函数。如果我从堆栈中取消boost :: shared_ptr而不是取消对象,那么我构建一个boost :: shared_ptr来进行调用!这正是我运行此代码时发生的情况:

double f(boost::shared_ptr<Obj>& object)
{
  ...
}

double g(Obj& object)
{
  boost::shared_ptr<Obj> p(&object);
  double x = f(p);
  ...
}

有没有办法让它发挥作用?我怎样才能在g()中创建一个boost :: shared指针,让我的对象在结束时保持活着状态?我想我必须将它连接到已经指向对象的其他共享指针的引用计数机制......但是如何?

即使我让它成功,你认为这种做法是糟糕的设计吗?解决这类问题的最佳做法是什么?在我的代码中,我有使用共享指针和引用的对象和方法,我不能只使用这些或那些......

6 个答案:

答案 0 :(得分:8)

采用shared_ptr的函数正在说明它的作用。它说,&#34;我想要声称这个对象的共享所有权&#34;。如果不是这样,那么这是一个写得不好的函数,根本不应该使用shared_ptr

通过非const引用对象获取值的函数意味着该函数可以修改该对象,但不能声明所有权。如果你不拥有某些东西,你也无法将权利交给其他人。

现在,您可以执行使用空删除函数的这一技巧:

void EmptyDeleter(Obj *) {}

double g(Obj& object)
{
  boost::shared_ptr<Obj> p(&object, EmptyDeleter);
  double x = f(p);
  ...
}

但是,您现在撒谎f。它不拥有object;它不能拥有objectobject很可能是一个堆栈对象,它可能在f完成后随时消失。如果f是类的成员,它可能会将shared_ptr存储在成员变量中。此时,它会有shared_ptr死对象。这正是shared_ptr旨在防止的事情。

正确的答案是f要求shared_ptr不要使用const(如果可修改则使用非const引用或非const&指针, g如果不可修改,或shared_ptr通过{{1}}获取参数。

答案 1 :(得分:4)

您可以创建一个实际上不释放该对象的shared_ptr。像这样:

struct FictiveDisposer {
    template <class T> void operator ()(T) {}
};

Obj& object = /* ... */;
boost::shared_ptr<Obj> myPtr(&obj, FictiveDisposer ());

// you may use myPtr

但是你应该仔细使用它。如果你确定你正在调用的函数不会试图“保存”你的对象供以后使用 - 那就没问题了。否则,必须保证对象保存的shared_ptr的生命周期不会超过对象的实际生命周期。

简单来说:你得到了对象的引用。你没有创建它,你可能不会影响它的生命周期(shared_ptr都不能)。因此,可能会出现对象不再存在的情况,仍由shared_ptr引用。必须避免这种情况。

答案 2 :(得分:1)

你必须考虑f()的目的。假设它需要一个shared_ptr,f打算保留该指针随时间的共享所有权,超过其返回值。为什么?什么是f()假设你传递一个shared_ptr?一旦你回答了这个问题,你将能够弄清楚如何编码g()。

如果由于某种原因f()不需要保留指针的共享所有权,那么如果你可以控制它的接口,它可以被重写为带Obj *或Obj&amp;而不是shared_ptr。拥有shared_ptr的任何代码都可以通过将指针拉出shared_ptr或解除引用来调用f。

答案 3 :(得分:0)

  

如何在g()中创建一个boost :: shared指针,使我的对象在结束时保持活动状态?

您可以为共享指针提供一个不执行任何操作的自定义析构函数:

boost::shared_ptr<Obj> p(&object, [](void*){});

或者如果您的编译器不支持lambdas:

void do_nothing(void*) {}
boost::shared_ptr<Obj> p(&object, do_nothing);
  

即使我开始工作,你认为这种做法是不好的设计吗?

是:您丢失了共享指针为您提供的生命周期管理,现在您有责任确保该对象超过所有共享指针。

  

解决此类问题的最佳做法是什么?

确定您正在使用的所有对象的所有权模型,并坚持下去。当您想要共享所有权时,共享指针可能很有用,但不是。在您的情况下,f想要分享所有权,而且g似乎想要拥有独占所有权;考虑他们为什么要这样做是一个好主意,以及你是否可以改变一个以与另一个兼容。

答案 4 :(得分:0)

这通常是图书馆界面设计不佳的标志 shared_ptr(但也有例外)。既然你的功能 打电话希望承担责任,或者至少是部分责任 对于传递它的对象以及其余代码的责任 对此没有准备,你唯一安全的解决方案是克隆 对象,例如:

double x = f( boost::shared_ptr<Obj>( new Obj( object ) ) );

但你真的最好找出f要求的原因 shared_ptr,以及为什么g不能将一个作为参数。

答案 5 :(得分:0)

std::shared_ptr<T>可以为多个实体提供所引用对象的所有权。如果接口需要std::shared_ptr<T>,则有两种可能性:

  1. 有人在接口中无意中使用std::shared_ptr<T>,该接口旨在接收T对象或引用或指向T对象的指针。如果是这种情况,作者将接受教育(如果这不起作用,从他目前的职责中解脱,以寻求新的职业)并更正界面。
  2. 从现在开始,所有使用std::shared_ptr<T>的接口都使用它来授予对象共享所有权,显然分配的T堆栈不适合这样的接口。唯一可能的参数是T对象,其生命周期维持在std::shared_ptr<T>
  3. 我意识到这并没有回答原来的问题,但应该清楚的是,唯一可行的做法是:不要试图将一个对象传递给一个带有{的函数{1}}这个指针无法完全控制! (这同样适用于共享指针的std::shared_ptr<T>版本。)