为什么我的COM智能指针在从func返回时尝试删除。我认为它仍然在范围内。有没有办法避免这种情况?
这是.TLH文件中的定义
_COM_SMARTPTR_TYPEDEF(IComItem, __uuidof(IComItem));
static IComItemPtr m_pItem;
LPDISPATCH func()
{
IComItemPtr pItem = m_pItem;
pItem = pItem->GetParent(); // Returns parent as IComItemPtr
return pItem; // Gets deleted here
}
答案 0 :(得分:3)
您的函数的返回类型是原始IDispatch*
指针,而不是IComItemPtr
对象(或至少是IDispatchPtr
个对象)。您看到的问题是由于您错误地将智能指针与原始指针混合在一起。
由于您的函数未返回智能包装器对象,因此必须执行转换才能将pItem
转换为IDispatch*
。在这种情况下pItem
可以执行的The only conversion是IComItem*
,然后编译器可以隐式转换为IDispatch*
(因为IComItem
派生自IDispatch
,否则你的代码根本就不会编译。)
IOW,你的return
语句实际上是在做这个逻辑:
LPDISPATCH func()
{
IComItemPtr pItem = m_pItem;
pItem = pItem->GetParent(); // Returns parent as IComItemPtr
//return pItem;
IComItem *pTemp = pItem.operator IComItem*();
IDispatch *pDisp = (IDispatch*) pTemp;
return pDisp;
} // <-- pItem is destructed here!
无论如何,pItem
本身在函数退出时总是超出范围,如果pItem
引用对象,则递减对象的引用计数。
所以,重要的是你返回一个IDispatch*
指向一个有效对象的指针,该对象的refcount递增,这样当pItem
的析构函数递减其引用计数时,对象不会被释放。
请改为尝试:
IComItemPtr func()
{
return m_pItem->GetParent(); // Returns parent as IComItemPtr
}
或者:
IDispatchPtr func()
{
return m_pItem->GetParent(); // Returns parent as IComItemPtr converted to IDispatchPtr
}
如果绝对必须返回原始IDispatch*
指针,则必须:
在退出之前手动递增引用计数:
LPDISPATCH func()
{
IComItemPtr pItem = m_pItem->GetParent(); // Returns parent as IComItemPtr
pItem.AddRef();
return pItem;
}
手动从包装器中分离指针:
LPDISPATCH func()
{
IComItemPtr pItem = m_pItem->GetParent(); // Returns parent as IComItemPtr
return pItem.Detach();
}
答案 1 :(得分:0)
您首先假设不正确。
static IComItemPtr m_pItem;
LPDISPATCH func()
{
IComItemPtr pItem = m_pItem;
pItem = pItem->GetParent();
return pItem; // not here.
} // Gets deleted here (this is where scope is closed).
在调用析构函数之前,返回会将pItem
从IComItemPtr
转换为LPDISPATCH
(IDispatch*
)。此转换的结果将放在目的地。
注意:转换的发生方式完全取决于所涉及类型的确切定义。