c++ - 关于使用CComPtr的一些问题(什么时候使用Release()?我可以返回CComPtr吗?,...)

标签 c++ com smart-pointers bho

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

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

  2. 在这个this用于发布的链接 浏览器对象。我还应该在哪里使用它?在“正常”使用中(使用我自己的类(class))我不需要它。我应该在这种情况下使用它吗:
    我使用 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 私有(private)函数是这样声明的:
    void RemoveImages(IHTMLDocument2 *pDocument); 
    但使用智能指针调用:
    CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc;
    if (spHTMLDoc != NULL)
    {
     // Finally, remove the images.
     RemoveImages(spHTMLDoc);
    }
    
    我宁愿这样写:
    void RemoveImages(CComPtr<IHTMLDocument2> document2);
    这个会比较好吗?

最佳答案

第一个问题。 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
}

您会看到,当 GetObject() 获取指针时,它会覆盖已存储在 CComPtr 中的值。如果 CComPtr 存储一个非空指针,它将被覆盖(浅拷贝)并且原始指针指向的对象将被泄漏。在第一个 GetObject() 之前不需要 Release() - 此时指针为空。在第二个 GetObject() 之后您不需要任何一个 - 一旦指针超出范围,该对象将被释放。

第二个问题。是的,您可以返回 CComPtr,但前提是调用方也将其接受到 CComPtr 中。以下代码:

ISomeInterface* pointer = YourFunctionReturningCComPtr();

不会取得该对象的所有权,因此该对象将被释放,指针 将变为悬挂状态。这是未定义的行为。

第三个问题 CComPtr 是关于所有权的。通常,将 CComPtr 作为“输入”参数传递是没有意义的,除非您确切地知道为什么要这样做。

关于c++ - 关于使用CComPtr的一些问题(什么时候使用Release()?我可以返回CComPtr吗?,...),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4284621/

相关文章:

c++ - 在调用 QWidget.setParent() 的过程后终止时发出 SIGSEGV

c++ - 模板类中具有未知类型属性的默认构造函数

java - 如何在多个 Java 线程中使用 COM 服务器

c++ - 抽象类继承和智能指针容器

rust - 如何将 Rc<RefCell<Box<MyStruct>>> 传递给接受 Rc<RefCell<Box<dyn MyTrait>>> 的函数?

c++ - 使用 RapidXML/C++ 类指针副作用进行解析时的递归问题

c# - C#中使用[using]语句好还是[dispose]方法好?这是否适用于外部 (COM) 对象?

c++ - COM 客户端连接 COM 服务器(进程外场景)所需的文件是什么?

c++ - unique_ptr<T> 用于数组特化的 lambda 自定义删除器

c++ - 是否允许构造 unsigned long long?