关于使用CComPtr的一些问题(当使用Release()时?我可以返回CComPtr吗?,...)

Mar*_*ski 11 c++ com bho smart-pointers

我为Internet Explorer(BHO)编写附加组件,我正在使用CComPtr智能指针.我想知道:

  1. 我什么时候应该使用CComPtr.Release()函数?

  2. 在这链接它是用来释放浏览器对象.我应该在哪里使用它?在'正常'使用(使用我自己的类)我不需要它.我应该在这种情况下使用它:
    我使用m_spWebBrowser-> get_Document(&spDispDoc)获取文档对象:
    void STDMETHODCALLTYPE CHelloWorldBHO::OnDocumentComplete(IDispatch *pDisp, VARIANT *pvarURL)
    {
        // Query for the IWebBrowser2 interface.
        CComQIPtr spTempWebBrowser = pDisp;
    
        // Is this event associated with the top-level browser?
        if (spTempWebBrowser && m_spWebBrowser &&
            m_spWebBrowser.IsEqualObject(spTempWebBrowser))
        {
            // Get the current document object from browser...
            CComPtr spDispDoc;
            hr = m_spWebBrowser->get_Document(&spDispDoc);
            if (SUCCEEDED(hr))
            {
                // ...and query for an HTML document.
                CComQIPtr htmlDoc2 = spDispDoc;
                m_spHTMLDocument = spHTMLDoc;
            }
        }
    
    }
    
    我应该像使用m_spWebBrowser一样在SetSite函数中释放spHTMLDocument(就像之前提到的链接一样)?
  3. 我可以安全地从函数返回CComPtr吗?
  4. 我的意思是这样的:
    CComPtr getObjects(CComQIPtr<IHTMLDocument3> htmlDoc3)
    {
     CComPtr objects;
     hr = htmlDoc3->getElementsByTagName(CComBSTR(L"object"), &objects);
     if(SUCCEEDED(hr) && objects != NULL)
     {
      return objects;
     }
     return NULL;
    }
    
  5. 我不应该使用普通指针吗?
  6. 在以前的链接中,RemoveImages私有函数以这种方式声明:
    void RemoveImages(IHTMLDocument2 *pDocument); 
    但是使用智能指针调用:
    CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc;
    if (spHTMLDoc != NULL)
    {
     // Finally, remove the images.
     RemoveImages(spHTMLDoc);
    }
    
    我宁愿这样写:
    void RemoveImages(CComPtr<IHTMLDocument2> document2);
    好点吗?

sha*_*oth 17

对第一个问题. CComPtr::Release()与指定对象的空指针具有相同的效果.Release()如果出于任何原因想要在指针超出范围之前释放对象,则可以调用(或指定空指针).例如:

CComPtr<ISomeInterface> pointer;
HRESULT hr = firstProvider->GetObject( &pointer );
if( SUCCEEDED( hr ) ) {
   //use the object
   pointer.Release();
}
HRESULT hr = secondProvider->GetObject( &pointer );
if( SUCCEEDED( hr ) ) {
   //use the object
}
Run Code Online (Sandbox Code Playgroud)

你看,当GetObject()获得指针时,它会覆盖已经存储的值CComPtr.如果CComPtr存储一个非空指针,它将被覆盖(浅拷贝),并且原始指针指向的对象将被泄露.您不需要Release()在第一个之前GetObject()- 指针在该点为空.而且你不需要在第二个之后GetObject()- 一旦指针超出范围,对象将被重新发送.

第二个问题.是的,您可以返回,CComPtr但仅在调用者也接受它时才能返回CComPtr.以下代码:

ISomeInterface* pointer = YourFunctionReturningCComPtr();
Run Code Online (Sandbox Code Playgroud)

不会取得对象的所有权,因此该对象将被释放pointer并将变为悬空.这是未定义的行为.

第三个问题 CComPtr是所有权.通常没有必要CComPtr作为"in"参数传递,除非你知道为什么要这样做.