ATL CComPtr附加、分离和析构函数

ATL CComPtr Attach, Detach and Destructor

本文关键字:析构函数 分离 CComPtr 附加 ATL      更新时间:2023-10-16

我想。。"附加"answers"分离"不会更改引用计数。但是CComPtr的析构函数调用释放它所包含的指针。

那么,每次使用attach时都有必要调用detach吗?。。。

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

}

正如您所提到的,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

与大多数智能指针一样,CComPtr<T>表示所有权,并使用RAII语义来确保正确清理所拥有的资源。AttachDetach方法用于转移所有权,部分原因是参考计数记账可能相对昂贵。因此,你需要在你的背景下回答的问题是所有权的模式是什么

当在两个CComPtr<T>对象之间转移所有权时,会有匹配AttachDetach调用的趋势,但它们将在单独的对象上:

    spFoo2.Attach(spFoo1.Detach());

考虑以下片段,以及它们对IFoo对象所有权的指示。m_spFoospFoo都是CComPtr<IFoo>值:

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());

以下是我对这些片段的看法。

  • 第一种是向调用方返回IFoo的非常常见的方式,遵循调用方接收具有递增引用计数的副本的常见语义
  • 第二种是可以的,如果所有权被传递给调用者;调用方获取CCD_ 20对象先前具有的副本
  • 第三种可能已经返回了CComPtr<IFoo>CComPtr<IFoo>&(非参考情况可能导致额外的参考计数记账),并且我们正在指示进一步的共享所有权;也就是说,我们希望将其保留更长的时间
  • 第四个表示GetFoo_4中不寻常的语义,因为它一定提供了原始IFoo*的引用计数,我们不想进一步增加