我为Internet Explorer(BHO)编写附加组件,我正在使用CComPtr智能指针。我想知道:
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(就像之前提到的链接一样)?
CComPtr getObjects(CComQIPtr<IHTMLDocument3> htmlDoc3) { CComPtr objects; hr = htmlDoc3->getElementsByTagName(CComBSTR(L"object"), &objects); if(SUCCEEDED(hr) && objects != NULL) { return objects; } return NULL; }
void RemoveImages(IHTMLDocument2 *pDocument);但是使用智能指针调用:
CComQIPtr<IHTMLDocument2> spHTMLDoc = spDispDoc; if (spHTMLDoc != NULL) { // Finally, remove the images. RemoveImages(spHTMLDoc); }我宁愿这样写:
void RemoveImages(CComPtr<IHTMLDocument2> document2);好点吗? 醇>
答案 0 :(得分: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
}
您会看到,当GetObject()
获取指针时,它会覆盖已存储在CComPtr
中的值。如果CComPtr
存储一个非空指针,它将被覆盖(浅拷贝),并且原始指针指向的对象将被泄露。在第一个Release()
之前不需要GetObject()
- 指针在该点为空。并且在第二个GetObject()
之后你也不需要 - 一旦指针超出范围,对象就会被重新发送。
至第二个问题。是的,您可以返回CComPtr
,但前提是调用者也接受CComPtr
。以下代码:
ISomeInterface* pointer = YourFunctionReturningCComPtr();
不会取得对象的所有权,因此对象将被释放,pointer
将变为悬空。这是未定义的行为。
对于第三个问题 CComPtr
是为了所有权。通常没有必要将CComPtr
作为“in”参数传递,除非您知道为什么要这样做。