2010-12-03 63 views
6

什麼是這樣做的正確方法:使用_bstr_t傳遞類型BSTR *的參數功能

_bstr_t description; 
errorInfo->GetDescription(&description.GetBSTR()); 

或:

_bstr_t description; 
errorInfo->GetDescription(description.GetAddress()); 

IError:GetDescription被定義爲:

HRESULT GetDescription (BSTR *pbstrDescription); 

我知道我很容易做到這一點:

BSTR description= SysAllocString (L"Whateva")); 
errorInfo->GetDescription (&description); 
SysFreeString (description); 

感謝

回答

8

的BSTR被引用計數,我嚴重懷疑,將工作的權利,如果您使用的getAddress()。可悲的是,源代碼不可用來仔細檢查。我一直在做這樣的:

BSTR temp = 0; 
HRESULT hr = p->GetDescription(&temp); 
if (SUCCEEDED(hr)) { 
    _bstr_t wrap(temp, FALSE); 
    // etc.. 
} 
+0

+1,其他實例共享的_bstr_t的BSTR的討論將我可能直接分配給它的任何東西都關閉。 – 2010-12-03 15:56:21

5

要在@跟進漢斯的答案 - 用適當的方式來構建_bstr_t取決於是否GetDescription回報你,你自己的BSTR,或一個引用的內存,你不要不必自由。

這裏的目標是儘量減少副本數量,但也要避免對返回的數據進行任何手動調用SysFreeString。我將修改代碼,如圖澄清這個:

BSTR temp = 0; 
HRESULT hr = p->GetDescription(&temp); 
if (SUCCEEDED(hr)) { 
    _bstr_t wrap(temp, false); // do not copy returned BSTR, which 
            // will be freed when wrap goes out of scope. 
            // Use true if you want a copy. 
    // etc.. 
} 
2

逾期答案可能並不適用於早期(或更高版本)版本的Visual Studio;但是, VS 12.0的內嵌實現_bstr_t,並且顯然當在原始_bstr_t上調用GetBSTR()時創建的內部Data_t實例的m_RefCount爲1。所以_bstr_t生命週期中的第一個例子看起來是好的:

_bstr_t description; 
errorInfo->GetDescription(&description.GetBSTR()); 

但如果_bstr_t是髒的,現有的內部m_wstr指針將被覆蓋,泄漏以前的記憶它引用。

通過使用以下operator&,可以使用髒_bstr_t,因爲它首先通過Assign(nullptr)清除。過載還提供了利用地址運算符而非GetBSTR()的便利;

BSTR *operator&(_bstr_t &b) { 
    b.Assign(nullptr); 
    return &b.GetBSTR(); 
} 

所以,你的第一個例子可以改爲如下所示:

_bstr_t description(L"naughty"); 
errorInfo->GetDescription(&description); 

此評估是基於comutil.h從VS 12.0。