我常写以下代码:IMyInterface* pi;
HRESULT hr = MyObject->QueryInterface(IID_IMyInterface, (void**)&pi);//MyObject是有效对象...use pi........
.....
......pi->Release();
通常情况下“pi->Release();”的执行不会引起MyObject的析构,但有时候会,谁能告诉我怎么判断在QueryInterface()后面是否要调用Release();“每个QueryInterface()后面总要调用Release()”到底对不对呢?

解决方案 »

  1.   

    This function must call IUnknown::AddRef on the pointer it returns. 
    --MSDN
    QueryInterface()函数内没有调用AddRef(),所以除非你能保证在当前作用域内该对象不会被释放,否则就一定要调用AddRef(),如果调用了AddRef(),也就应当在使用完后调用Release()
      

  2.   

    呵呵,仔细看了一下,误解了MSDN上的意思,原文的意思是说在QueryInterface函数中,在返回相应的指针之前必须调用AddRef(),记得在COM技术内幕这本书中曾经说过像CoCreateInstance、CreateInstance、QueryInterface之类函数在返回之前都已经调用过AddRef函数,所以不用再自己调用一次AddRef,只需要在用后调用Release即可。
    下面是ATL头文件AtlBase.h中AtlInternalQueryInterface函数的实现
    ATLINLINE ATLAPI AtlInternalQueryInterface(void* pThis,
    const _ATL_INTMAP_ENTRY* pEntries, REFIID iid, void** ppvObject)
    {
    ATLASSERT(pThis != NULL);
    // First entry in the com map should be a simple map entry
    ATLASSERT(pEntries->pFunc == _ATL_SIMPLEMAPENTRY);
    if (ppvObject == NULL)
    return E_POINTER;
    *ppvObject = NULL;
    if (InlineIsEqualUnknown(iid)) // use first interface
    {
    IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
    pUnk->AddRef();
    *ppvObject = pUnk;
    return S_OK;
    }
    while (pEntries->pFunc != NULL)
    {
    BOOL bBlind = (pEntries->piid == NULL);
    if (bBlind || InlineIsEqualGUID(*(pEntries->piid), iid))
    {
    if (pEntries->pFunc == _ATL_SIMPLEMAPENTRY) //offset
    {
    ATLASSERT(!bBlind);
    IUnknown* pUnk = (IUnknown*)((int)pThis+pEntries->dw);
    pUnk->AddRef();
    *ppvObject = pUnk;
    return S_OK;
    }
    else //actual function call
    {
    HRESULT hRes = pEntries->pFunc(pThis,
    iid, ppvObject, pEntries->dw);
    if (hRes == S_OK || (!bBlind && FAILED(hRes)))
    return hRes;
    }
    }
    pEntries++;
    }
    return E_NOINTERFACE;
    }可以看到在返回接口指针之前已经调用过AddRef,因此自己是不用再调了的
      

  3.   

    firmbird(firmbird):我写了这样一个类
    class CMyClass : 
    public ISupportErrorInfo,
    public CComObjectRootEx<CComMultiThreadModel>,
    public CComCoClass<CMyClass,&CLSID_MyClass>,
    public IDispatchImpl<IMyInterface, &IID_IMyInterface, &LIBID_MyLib>
    {
    ...
    }
    在程序中如下使用:
    CComObject<CMyClass>  *m_pObj;//成员变量CComObject<CMyClass>::CreateInstance(&m_pObj);//创建
    IMyInterface* t=NULL;
    m_pObj->QueryInterface(IID_IMyInterface, (void**)&t);
    ....//使用
    t->Release();会导致m_pObj析构。注:使用过程中只是调用了接口的方法如果ATL中的QueryInterface()自动调用AddRef(),为什么我会得到以上结果?
      

  4.   

    我说的CreateInstance是类工厂上的方法,不是CComObject基类中的方法,CComObject的CreateInstance方法并没有使用对象的引用计数增加,当你调用Release()方法时就会引起对象析构