shared_ptr vs CComPtr

时间:2012-02-11 19:50:35

标签: c++ com shared-ptr

我有点习惯通过COM引用引用计数的概念,而且我对shared_ptr有些新意。 CComPtr有几个不错的属性,我在shared_ptr中找不到,我想知道什么是防止错误使用shared_ptr的模式。

  • AddRef / Release模式保证每个对象只有一个refcount(refcount存储在对象本身上),所以当你有一个随机指针在它周围创建一个CComPtr时它是安全的。另一方面,shared_ptr有一个单独的refcount指针,因此在一个对象上创建一个新的shared_ptr是不安全的(为什么标准提供了一个构造函数,如果它不安全那么在shared_ptr上取一个T *)。这似乎是一个很大的限制,我不明白如何使用shared_ptrs ......

  • 一个小角落的案例:我过去用AddRef / Release做过的事情:我想要一个对IFoos有“弱引用”的容器(例如从URL到IConnection的地图或其他东西)。使用weak_ptr,我可以做到这一点,但我的收藏不会“清理自己”,我会在其中过期指针。使用Release,我可以实现我自己的弱指针(一些工作),它实际上清理了集合。是否有使用shared / weak_ptr的替代方法?

  • 直观地说,在执行两次内存分配以创建对象(一个用于引用计数,一个用于对象)与IUnknown世界(仅执行一个对象)相比,存在性能损失。访问对象时也存在局部性损失(假设经常跟随AddRef读取对象的内容,这似乎很可能)。这两种方法的成本是否已经进行了比较?

1 个答案:

答案 0 :(得分:4)

  

为什么标准提供了一个构造函数,如果它不安全的话,它会在shared_ptr上获取T *?

因为这是shared_ptr没有侵入性的唯一方法。您可以在任何上使用shared_ptr。我甚至通过使用删除对象在C接口的对象上使用它们。像cairo_t*等等。这样,我再也不用任何东西了。

CComPtr你无法做到这一点;它只适用于IUnknown - 样式的对象。

此外,还有std::make_shared,它直接从对象类型和构造函数的参数创建shared_ptr。所以你甚至从来没有看到指针(它通常在一个分配而不是两个分配中分配对象及其引用计数。)

使用shared_ptr的正确C ++习语非常简单:始终使用make_sharedalloc_shared。如果无法使用它们,那么正确的习惯用法是使用直接裸指针构造函数与newshared_ptr<T> pVal{new T{...}};一起使用(或者创建指针的适当函数。切勿在不知道原点的指针上使用它。

  

是否有使用shared / weak_ptr的替代方法?

不,但如果您愿意,还有工具可以制作一个。除了显而易见的方法(定期运行您的集合并删除死weak_ptr),您可以将删除器与shared_ptr相关联(除了删除指针之外)调用任何清理函数来删除那些weak_ptr秒。

  

直观地说,在进行两次内存分配以创建对象时存在性能损失

请参阅上面的make_shared

  

访问对象时也存在局部性损失(假设经常跟随AddRef读取对象的内容,这似乎很可能)。

您无需复制shared_ptr即可与其内容进行对话,也无需违反引用计数。

现在,我们来谈谈CComPtr 无法做的一些事情。这是侵入性的。它不能与任意分配器或删除器一起使用(当它是侵入时显然不那么重要)。它不能执行指针别名,对象的成员有shared_ptr,但实际的引用计数是它所属的对象。这是一件非常有用的事情。

哦,是的,不是跨平台的。它不受COM,IUnknown以及所有 开销的限制。