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

进行管理

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

但我感到内疚,迫使我的用户合理。

让库向其对象公开weak_ptr是否可以接受?还有其他图书馆吗?

我已经在应用程序中描述了这个库的用法,并发现它对于完全暴露<=>非常关键。

让匹配的API函数公开引用一个weak_ptr或使任何对象能够将<=>暴露给自己吗?

有帮助吗?

解决方案

如果smart_ptr已经可以直接访问库的用户,那么他们已经可以通过相应的weak_ptr的构造函数访问shared_ptr了。但是如果<=> s都是库的内部,那就是另一个故事。

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

当然,我不知道你的图书馆做了什么,或者它是如何使用或设计的。这可能会改变我的建议。

其他提示

使用复杂的机制来获取图书馆的对象只会导致人们不使用您的图书馆。如果库的语义决定你需要让人们使用weak_ptrs,那么用户就无法知道对象可能会在某些时候消失。使界面尽可能多地表达有关库使用的信息,保持文档记录并使其更容易使用。

你不能围绕坏/没有经验的用户进行设计。

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

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

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

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

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

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

为简单起见,我们假设您只展示了一类对象;称这个类为Object。然后,从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()高于零,即对象仍然存在。如果对象已被释放,则会出现失败的断言,这比空指针引用要好。

一般情况下,如果你有<!>“stupid <!>”,那么使用weak_ptr是没有用的。 API的用户,因为他们可以调用lock()然后在weak_ptr返回一个为空的shared_ptr之后仍然进行空指针引用...

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top