Shared_ptr 与 CComPtr

2023-11-26

我已经习惯了通过 COM 进行引用计数的概念,并且对 shared_ptr 有点陌生。 CComPtr 有几个不错的属性,但我在共享指针中找不到,我想知道防止滥用共享指针的模式是什么。

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

  • 有点极端的情况:我过去用 AddRef/Release 做过的事情:我想要一个对 IFoos 的“弱引用”容器(例如从 URL 到 IConnection 的映射或其他东西)。使用weak_ptr,我可以做到这一点,但我的集合不会“自我清理”,其中会有过期的指针。通过 Release,我可以实现自己的弱指针(需要做一些工作)来实际清理集合。有没有shared/weak_ptr的替代方案?

  • 直观上,与仅执行一次的 IUnknown 世界相比,执行两次内存分配来创建对象(一次用于引用计数,一次用于对象)会带来性能损失。访问对象时还存在局部性惩罚(假设 AddRef 后经常读取对象的内容,这似乎是可能的)。是否比较了两种方法的成本?


如果这样做如此不安全,为什么标准提供一个在shared_ptr上接受T*的构造函数?

因为这是唯一的途径shared_ptr不存在侵扰性的。您可以使用shared_ptr on anything。我什至通过使用删除器对象在 C 接口的对象上使用它们。事情就像cairo_t*等等。这样,我就再也不用释放任何东西了。

你不能这样做CComPtr;它只适用于IUnknown风格的对象。

另外,还有std::make_shared,这会创建一个shared_ptr直接从对象类型和构造函数的参数。因此,您甚至永远不会看到指针(并且它通常在一次分配而不是两次分配中分配对象及其引用计数)。

正确的 C++ 习惯用法是shared_ptr很简单:总是使用make_shared or alloc_shared。如果你can't使用它们,那么正确的习惯用法是only结合使用直接裸指针构造函数new: shared_ptr<T> pVal{new T{...}};(或创建指针的适当函数)。切勿在您不知道其来源的指针上使用它。

有没有shared/weak_ptr的替代方案?

不,但是如果您愿意,可以使用一些工具来制作。除了明显的方法(定期检查你的收藏并删除死的weak_ptrs),您可以将删除器与shared_ptr这将(除了删除指针之外)调用任何清理函数来删除那些weak_ptrs.

直观上,进行两次内存分配来创建对象会带来性能损失

See make_shared, above.

访问对象时还存在局部性惩罚(假设 AddRef 后经常读取对象的内容,这似乎是可能的)。

您不必复制shared_ptr来谈论它的内容,你也不必增加引用计数来做到这一点。

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

哦,是的,这是不跨平台。它不绑定到COM,IUnknown,以及所有的that高架。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Shared_ptr 与 CComPtr 的相关文章

随机推荐