use*_*233 4 c++ com shared-ptr
我有点习惯于通过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,我可以实现自己的弱指针(需要一些工作),实际上可以清理集合。有共享/ weak_ptr的替代方法吗?
直观地讲,与仅执行一个操作的IUnknown世界相比,执行两个内存分配来创建一个对象会降低性能(一个用于refcount,一个用于该对象)。访问对象时,也会受到局部性的影响(假设AddRef经常跟随读取对象的内容,这似乎是可能的)。是否比较了两种方法的成本?
标准为何提供这样做的构造函数,如果这样做非常不安全,该构造函数会在shared_ptr上采用T *?
因为这是拥有shared_ptrs而不被干扰的唯一方法。您可以shared_ptr在任何东西上使用。通过使用Deleter对象,我什至在C接口的对象上使用了它们。诸如a之类的东西cairo_t*。这样,我再也不必释放任何东西了。
你不能用CComPtr; 它仅适用于IUnknown-style对象。
此外,还有std::make_shared,它shared_ptr直接从对象类型和构造函数的参数创建一个。因此,您甚至都看不到指针(它通常以一种分配而不是两种分配方式分配对象及其引用计数)。
正确的C ++用法shared_ptr非常简单:始终使用make_shared或alloc_shared。如果您不能使用它们,那么适当的习惯用法是仅将直接裸指针构造函数与new:组合使用shared_ptr<T> pVal{new T{...}};(或创建指针的适当函数)。切勿在您不知道其起源的指针上使用它。
有shared / weak_ptr的替代方法吗?
不,但是如果您愿意,可以使用一些工具来制作。除了显而易见的方法(定期运行您的集合并删除dead weak_ptr)之外,您还可以将Deleter与shared_ptr,它将(除了删除指针之外)调用任何清理函数以删除这些weak_ptrs 关联。
直观地讲,进行两次内存分配以创建对象会降低性能
参见make_shared上方。
访问对象时,也会受到局部性的影响(假设AddRef经常跟随读取对象的内容,这似乎是可能的)。
您无需复制shared_ptr即可与其内容进行对话,也不必增加引用计数即可。
现在,让我们谈谈一些CComPtr 无法做到的事情。太麻烦了 它不能与任意的分配器或删除器一起使用(显然,当它具有侵入性时,它并不那么重要)。它不能执行指针别名,即您拥有shared_ptr对象的成员,但是实际引用计数是针对对象所属的对象。这是一件非常有用的事情。
哦,是的,它不是跨平台的。它不限于COM IUnknown以及所有这些开销。