我有点习惯于通过COM进行计数的概念,而我对shared_ptr还是有些陌生。我没有在shared_ptr中找到CComPtr的几个不错的属性,并且我想知道什么是防止滥用shared_ptr的模式。

  • AddRef/Release模式可确保每个对象只有一个引用计数(引用计数存储在对象本身上),因此,当您有随机指针围绕它创建CComPtr时,这是安全的。另一方面,shared_ptr有一个单独的refcount指针,因此在一个对象上创建一个新的shared_ptr是不安全的(为什么标准这样做会提供一个在shared_ptr上使用T *的构造函数呢?)。这似乎是一个很大的限制,以至于我不明白如何使用shared_ptrs ...
  • 一个极端的情况:我过去使用AddRef/Release所做的事情:我想要一个对IFoos的“弱引用”的容器(例如,从URL到IConnection的映射等)。使用weak_ptr,我可以做到这一点,但是我的集合不会“清理自身”,我将拥有过期的指针。使用Release,我可以实现自己的弱指针(需要一些工作),实际上可以清理集合。有shared/weak_ptr的替代方法吗?
  • 直观上讲,与仅执行一个操作的IUnknown世界相比,执行两个内存分配来创建一个对象(一个用于引用计数,一个用于该对象)会降低性能。访问对象时,也会受到局部性的影响(假设AddRef经常跟随读取对象的内容,这似乎是可能的)。是否比较了两种方法的成本?

    最佳答案



    因为这是拥有shared_ptr而不被打扰的唯一方法。您可以在任何东西上使用shared_ptr。通过使用Deleter对象,我什至在C接口(interface)的对象上使用了它们。诸如cairo_t*之类的东西。这样,我再也不必释放任何东西了。

    您不能使用CComPtr来做到这一点;它仅适用于IUnknown样式的对象。

    另外,还有std::make_shared,它直接从对象类型和构造函数的参数创建shared_ptr。因此,您甚至都看不到指针(它通常以一种分配而不是两种分配方式分配对象及其引用计数)。

    正确的带有shared_ptr的C++习惯用法非常简单:始终使用make_sharedalloc_shared。如果不能使用它们,那么适当的习惯用法是仅将直接裸指针构造函数与new:shared_ptr<T> pVal{new T{...}};(或创建指针的适当函数)串联使用。切勿在您不知道其起源的指针上使用它。



    不,但是如果您愿意,有一些工具可以使之成为现实。除了显而易见的方法(定期运行您的集合并删除不起作用的weak_ptr)之外,您还可以将Deleter与shared_ptr关联,该weak_ptr将(除了删除指针之外)调用任何清理函数来删除这些make_shared s。



    参见上面的shared_ptr



    您无需复制CComPtr即可与其内容对话,也无需增加引用计数即可。

    现在,让我们谈谈shared_ptr无法完成的一些事情。太麻烦了它不能与任意的分配器或删除器一起使用(显然,当它具有侵入性时,它并不那么重要)。它无法执行指针别名操作,在这里,您有一个指向对象成员的IUnknown,但实际引用计数是针对该对象所属的对象的。这是一件非常有用的事情。

    哦,是的,它不是跨平台的。它不限于COM,ojit_code和所有这些开销。

    10-08 09:44