【问题标题】:ATL CComPtr Attach, Detach and DestructorATL CComPtr 附加、分离和析构函数
【发布时间】:2014-12-28 12:50:10
【问题描述】:

我认为.. 附加和分离不会改变引用计数。 但是 CComPtr 的析构函数调用释放它包含的指针。

那么是不是每次使用attach的时候都要调用detach呢?...

{
    CComPtr<IObj> pPtr;
    pPtr.Attach(pPtr1);
    .....//No detach on pPtr

}

【问题讨论】:

    标签: c++ visual-c++ com atl


    【解决方案1】:

    正如您所提到的,Attach/Detach 在设计上不会影响引用计数器。因此,当您有特殊需要跳过添加参考时,您将使用它们。否则,您会以更自然的方式初始化指针(构造函数、赋值运算符等)。

    您对Attach 的特殊需求通常是为了补偿已添加的外部参考。这样您的 CComPtr 析构函数就会在需要时正确释放它。

    所以,不,您不必将AttachDetach 配对。当你必须的时候,你应该不会首先使用 Attach。

    例如Attach:

    {
      // We have an oustanding reference on pRawFoo we want to safely compensate for
      CComPtr pFoo;
      pFoo.Attach(pRawFoo); // No effect on counter, but since here we would release 
                            // the reference going out of scope
      // ...
    } // ~CComPtr releases the reference as intended
    

    Attach不需要:

    {
      // External pRawFoo is in proper balance in terms of reference count
      CComPtr pFoo;
      pFoo = pRawFoo; // No need in Attach, pFoo adds a reference
      // ...
    } // ~CComPtr releases the reference as intended
    

    【讨论】:

      【解决方案2】:

      像大多数智能指针一样,CComPtr&lt;T&gt; 表示所有权并使用 RAII 语义来确保正确清理拥有的资源。方法AttachDetach 用于转移所有权,部分原因是引用计数簿记可能相对昂贵。因此,您需要在您的上下文中回答的问题是所有权模式是什么。

      在两个 CComPtr&lt;T&gt; 对象之间转移所有权时,将倾向于匹配 AttachDetach 调用,但它们将在单独的对象上:

          spFoo2.Attach(spFoo1.Detach());
      

      考虑以下 sn-ps 以及它们对IFoo 对象所有权的指示。 m_spFoospFoo 都是 CComPtr&lt;IFoo&gt; 值:

      HRESULT C::GetFoo_1(IFoo **ppFoo)
      {
          return m_spFoo.QueryInterface(ppFoo); // or m_spFoo.CopyTo(ppFoo)
      }
      
      HRESULT C::GetFoo_2(IFoo **ppFoo)
      {
          *ppFoo = m_spFoo.Detach();
          return S_OK;
      }
      
          spFoo = obj.GetFoo_3();
      
          spFoo.Attach(obj.GetFoo_4());
      

      这是我对这些 sn-ps 的看法。

      • 第一种是向调用者返回 IFoo 的非常常用的方法,遵循通常的语义,其中调用者接收具有递增引用计数的副本。
      • 如果所有权被传递给调用者,第二个是可以的;调用者获取 C 对象之前拥有的副本。
      • 第三个可能已经返回CComPtr&lt;IFoo&gt;CComPtr&lt;IFoo&gt;&amp;(非引用情况会导致额外的引用计数簿记),我们表示进一步共享所有权;也就是说,我们希望将其保留比该声明更长的时间。
      • 第四个表示GetFoo_4 中的不寻常语义,因为它必须在原始IFoo* 上提供了一个我们不想进一步增加的引用计数。

      【讨论】:

        猜你喜欢
        • 2014-05-13
        • 1970-01-01
        • 2018-12-15
        • 2016-12-22
        • 1970-01-01
        • 2014-03-30
        • 1970-01-01
        • 2015-01-03
        • 2018-06-15
        相关资源
        最近更新 更多