眾所周知,在C/C++中,字符串通常采用“以0結束的字符數組”來表示,而在Visual Basic中,字符串則采用“字符數組加長度前綴的方法”來表示。
COM是一個支持多語言的通用組件,它內部到底采用什么樣的字符串類型呢?據說這個問題在微軟內部經過很長時間的爭論,最終VB派的人占了上風,這也直接導致COM在其內部采用BSTR(Basic String,Basic字符串)來作為其字符串類型。
BSTR被定義為OLECHAR*類型,查看OLECHAR類型的聲明,可以發現它其實是一個wchar_t類型,也就是說一個BSTR字符串其實是一個UNICODE字符串。
COM中一共提供了兩個類來對BSTR進行封裝,一個是編譯器提供的COM支持類:_bstr_t,另一個則是ATL庫提供的包裹類:CComBSTR。
_bstr_t提供的封裝層次較低,它僅提供簡單的字符串構造、連接以及比較操作,在某種意義上,它更像是一個萬能轉換頭,提供char*、wchar_t*類型到BSTR類型之間的轉換。

關於_bstr_t,需要注意的有三點:一是,它內部采用引用計數來管理字符串數組的生命周期;二是,它在構造或操作的過程是有可能拋出異常的;三是,它內部使用SysAllocString和SysFreeString來分配和釋放內存,在調用Detach操作之后,_bstr_t內“包裹”的BSTR字符串就會脫離出來,脫離出來的BSTR字符串,是需要手動調用SysFreeString來釋放內存的,否則會造成內存泄露問題。
CComBSTR提供的封裝層次更高,如果要操作BSTR,建議使用CComBSTR。

在使用CComPtr時的注意事項如下:
1、轉換問題:雖然一些 CComBSTR 方法自動將 ANSI 字符串參數轉換為 Unicode,但這些方法總是返回 Unicode 格式的字符串。若要將輸出字符串轉換回 ANSI,請使用 ATL 轉換類。另外,如果使用字符串來修改 CComBSTR 對象,請使用寬字符字符串。這會減少不必要的轉換。
2、范圍問題:與任何功能完善的類一樣,CComBSTR 在超出范圍時將釋放其資源。如果函數返回指向 CComBSTR 字符串的指針,這會引起問題,因為指針將引用已經釋放的內存。在這種情況下,請使用 Copy 方法。
3、顯式釋放 CComBSTR 對象:在對象超出范圍之前,可以手動調用SysFreeString顯式釋放包含在 CComBSTR 對象中的字符串。如果字符串被釋放,則 CComBSTR 對象無效。
4、在循環中使用 CComBSTR 對象:在CComBSTR 類分配緩沖區來執行某些運算時,如 += 運算符或 Append 方法,建議不要在緊密型循環內執行字符串操作。在這種情況下,CString可以提供更好的性能;
5、將已初始化的 CComBSTR 的地址作為 [out] 參數傳遞到函數會導致內存泄漏。若要避免泄漏,請在作為 [out] 參數傳遞地址之前,對現有的 CComBSTR 對象調用 Empty 方法。請注意,如果函數的參數是 [in, out],則同樣的代碼將不會導致泄漏。
具體說明可參考MSDN官方文檔 http://msdn.microsoft.com/zh-cn/library/cc485249(v=vs.71).aspx
