4

我编写了一个库,它公开了对几种相关对象类型的引用。所有这些对象的生命周期都由库内部通过boost::shared_ptr

库的用户还可以根据库的性质知道任何暴露对象的生命周期。所以他们可以存储指针或保留对这些对象的引用。他们这样做并知道这些对象何时不再有效是合理的。

但我对强迫我的用户讲道理感到内疚。

weak_ptr让库公开其对象是否可以接受?其他图书馆有这样做过吗?

我已经分析了这个库在应用程序中的使用情况,发现它对任务至关重要,无法weak_ptr专门公开。

让匹配的 API 函数公开引用weak_ptr 或让任何对象能够将 a 公开weak_ptr给自身会更明智吗?

4

5 回答 5

6

如果smart_ptr库的用户已经可以直接访问 s,那么他们已经可以访问weak_ptrs,只需通过相应weak_ptr的构造函数即可。但如果smart_ptrs 都是图书馆内部的,那就另当别论了。

weak_ptr在这种情况下,除了您的库提供的任何其他访问权限之外,我建议让每个对象将s 传递给自己。这为用户提供了最大的灵活性:如果他们需要 a weak_ptr,他们可以立即访问它;如果他们需要一个shared_ptr,他们可以很容易地得到它;如果他们只需要访问对象本身,他们可以完全忽略智能指针。

当然,我不知道您的库是做什么的,也不知道它是如何使用或设计的。这可能会改变我的建议。

于 2009-03-15T02:05:55.223 回答
4

想出复杂的机制来获取你图书馆的对象只会导致人们不使用你的图书馆。如果库的语义要求您需要让人们使用weak_ptrs,那么用户就无法知道对象可能会在某个时候消失。使界面尽可能多地表达有关库使用的信息,减少文档并使其无限易于使用。

您不能围绕糟糕/没有经验的用户进行设计。

于 2009-03-18T17:35:36.847 回答
2

如果您让您的客户访问weak_ptrs,他们可以锁定它们以创建shared_ptrs 并最终延迟对象的销毁。这可能会导致您的库出现问题。

我建议将 a 包装weak_ptr在其他类中,然后给调用者 a shared_ptr。这样他们就不能打电话了weak_ptr<T>::lock()。您似乎有可能影响您如何实现它的性能限制,但shared_ptr<InterfaceClass>可能是一个很好的方法,并将类与weak_ptr您的库的内部保持一致。

这样,您还可以将这些实现细节保留在库接口之外,并且您可以在不更改接口的情况下更改实现方式。

于 2009-03-17T04:59:21.920 回答
1

我认为暴露weak_ptrs 没有任何问题,特别是考虑到TR1 具有类似的智能指针(PDF)。

TR1 主要由 Visual Studio 和 GCC 实现,但不是其他一些编译器。但是,当它在您关心的所有编译器中实现时,您可能需要重新设计 API 以公开这些智能指针。

于 2009-03-10T17:27:40.340 回答
0

如果您想捕获库的无效使用(尝试在对象被删除时访问它们)以及拥有高性能 API(API 中没有weak_ptr和shared_ptr),那么您可以考虑使用不同的API用于调试和非调试版本。

为简单起见,我们假设您只公开了一类对象;调用这个类对象。从 API 返回的用于访问内部对象的指针类型定义为:

#ifdef DEBUG
typedef ObjectPtrFacade ObjectPtr 
#else
typedef Object * ObjectPtr;
#endif

这里的外观是你写的类。它的工作原理大致如下:

class ObjectPtrFacade {
public:
    ObjectPtrFacade(Object *o) : wptr(o) { }
    // copy constructor and assignment here etc. (not written)
    Object * operator -> () const { return access(); }
    Object & operator * () const { return *access(); }
private:
    Object * access() { 
      assert(wptr.use_count() > 0);
      return (Object *)(wptr.lock());
    }
    weak_ptr<Object> wptr; 
}

这样,每当您构建调试版本时,都会使用一种特殊类型的智能指针,它在访问对象之前断言其 use_count() 大于零,即该对象仍然存在。如果对象已被释放,您会得到一个失败的断言,这比空指针引用要好。

一般来说,如果你有 API 的“愚蠢”用户,当然使用weak_ptr 并没有帮助,因为他们可以调用lock(),然后在weak_ptr 返回一个空的shared_ptr 之后仍然进行空指针引用。 ..

于 2009-03-21T01:57:43.913 回答