【发布时间】:2014-12-28 12:50:10
【问题描述】:
我认为.. 附加和分离不会改变引用计数。 但是 CComPtr 的析构函数调用释放它包含的指针。
那么是不是每次使用attach的时候都要调用detach呢?...
{
CComPtr<IObj> pPtr;
pPtr.Attach(pPtr1);
.....//No detach on pPtr
}
【问题讨论】:
标签: c++ visual-c++ com atl
我认为.. 附加和分离不会改变引用计数。 但是 CComPtr 的析构函数调用释放它包含的指针。
那么是不是每次使用attach的时候都要调用detach呢?...
{
CComPtr<IObj> pPtr;
pPtr.Attach(pPtr1);
.....//No detach on pPtr
}
【问题讨论】:
标签: c++ visual-c++ com atl
正如您所提到的,Attach/Detach 在设计上不会影响引用计数器。因此,当您有特殊需要跳过添加参考时,您将使用它们。否则,您会以更自然的方式初始化指针(构造函数、赋值运算符等)。
您对Attach 的特殊需求通常是为了补偿已添加的外部参考。这样您的 CComPtr 析构函数就会在需要时正确释放它。
所以,不,您不必将Attach 与Detach 配对。当你必须的时候,你应该不会首先使用 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 语义来确保正确清理拥有的资源。方法Attach 和Detach 用于转移所有权,部分原因是引用计数簿记可能相对昂贵。因此,您需要在您的上下文中回答的问题是所有权模式是什么。
在两个 CComPtr<T> 对象之间转移所有权时,将倾向于匹配 Attach 和 Detach 调用,但它们将在单独的对象上:
spFoo2.Attach(spFoo1.Detach());
考虑以下 sn-ps 以及它们对IFoo 对象所有权的指示。 m_spFoo 和 spFoo 都是 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());
这是我对这些 sn-ps 的看法。
IFoo 的非常常用的方法,遵循通常的语义,其中调用者接收具有递增引用计数的副本。C 对象之前拥有的副本。CComPtr<IFoo> 或CComPtr<IFoo>&(非引用情况会导致额外的引用计数簿记),我们表示进一步共享所有权;也就是说,我们希望将其保留比该声明更长的时间。GetFoo_4 中的不寻常语义,因为它必须在原始IFoo* 上提供了一个我们不想进一步增加的引用计数。【讨论】: