CComBSTR
是
ATL
提供的
BSTR
包裝類,是
VC 6
中提供的最完善的
BSTR wrapper
。就像
MFC CString
提供了對(duì)
TCHAR
的封裝,
CComBSTR
提供了對(duì)
BSTR
的封裝。
Table 1 CComBSTR Methods
列出了
CComBSTR
的主要方法。
?
??????
CComBSTR Method
|
Description
|
CComBSTR
|
多個(gè)版本的構(gòu)造函數(shù)用來(lái)創(chuàng)建新的
BSTR
。可以使用的參數(shù)包括
LPCOLESTR, LPCSTR, CComBSTR
。
|
~CComBSTR, Empty
|
釋放內(nèi)部封裝的
BSTR.
|
Attach, Detach, Copy
|
Attach
把一個(gè)已經(jīng)存在
BSTR
加入類中。
Detach
把劣種的
BSTR
剝離,以便在超出作用域的時(shí)候,析構(gòu)函數(shù)不會(huì)釋放
BSTR
。
Detach
用于把
CComBSTR
賦給
[out]
參數(shù)。
Copy
用于產(chǎn)生一個(gè)
BSTR
的副本。一般用于用于把
CComBSTR
內(nèi)容賦給
[out]
參數(shù)。
|
operator BSTR, operator&
|
允許直接操作內(nèi)部的
BSTR
。
operator BSTR
用于把
CComBSTR
傳給
BSTR
輸入
[in]
參數(shù)。
operator&
用于把
CComBSTR
傳給
BSTR*
類型輸出
[out]
參數(shù)。
|
operator=, operator+=, operator<, operator==, operator>
|
重載運(yùn)算符,用于賦值、字符串連接、簡(jiǎn)單比較。
|
Append, AppendBSTR
|
字符串連接
|
Length
|
計(jì)算字符串長(zhǎng)度
|
LoadString
|
利用字符串資源初始化
BSTR
。
|
ToLower, ToUpper
|
字符串大小寫(xiě)轉(zhuǎn)換。
|
WriteToStream,ReadFromStream
|
從
IStream
中讀
/
寫(xiě)
BSTR
。
|
?
?
?
下面的偽代碼展示了
CComBSTR
的典型用法:
?HRESULT CMyObject::MyMethod(IOtherObject* pSomething)
{
??? CComBSTR bstrText(L"Hello");
??? bstrText += " again";???????????????????? // LPCSTR conversion
??? bstrText.ToUpper();
??? pSomething->Display(bstrText);??????????? // [in] parameter
??? MessageBoxW(0, bstrText, L"Test", MB_OK); // Assumes Windows NT
}
?
?
對(duì)于熟悉
MFC
的程序員,
CComBSTR
讓人失望。很多
CString
提供的方便的特性
CComBSTR
都沒(méi)有提供。重要的缺省列在了
Table 2 ?Notable CComBSTR Omissions
中。
簡(jiǎn)而言之,
CComBSTR
沒(méi)有提供完整的字符串操作。它的主要用途是把
LPCTSTR
轉(zhuǎn)換成
BSTR
,同時(shí)提供一個(gè)操作
BSTR
的類,使程序員可以不使用
COM SysXXXXString APIs
。如果需要使用復(fù)雜的字符串操作,可以使用
STL
提供的
wstring
類。
Table
2
?Notable CComBSTR Omissions
Features Not Included in CComBSTR
|
Explanation
|
LPCSTR extraction
|
CComBSTR
可以把一個(gè)單字節(jié)字符串轉(zhuǎn)換成
BSTR
,但是沒(méi)有提供反向轉(zhuǎn)換的功能。
_bstr_t
提供了
LPCTSTR operator
。
|
String manipulation (including Replace, Insert, Delete, Remove, Find, Mid, Left, Right, and so on)
|
CComBSTR
沒(méi)有提供這些方法。如果需要,可以使用
STL
中的
wstring
。
|
Language-sensitive collation
|
CComBSTR
提供的字符串比較
(<, >, ==)
按照是
byte-by-byte
方式進(jìn)行的。沒(méi)有提供語(yǔ)言相關(guān)的比較
(language-specific collation)
。如果需要可以使用
wstring.
|
?
使用
CComBSTR
時(shí)需要考慮的問(wèn)題。
?
·????????????????????
CComBSTR
初始化
CComBSTR
提供了一個(gè)長(zhǎng)度初始化函數(shù),
CComBSTR(int nSize)
。所以簡(jiǎn)單給
CComBSTR
初始化成
NULL
會(huì)發(fā)生意想不到的調(diào)用。
// CComBSTR(int nSize) is called
。
CComBSTR bstr1 =?NULL;?
CComBSTR bstr2(NULL);
?
// CComBSTR(LPCOLESTR pSrc) is called.
CComBSTR bstr3 =?static_cast<
LPCOLESTR>(NULL);
CComBSTR bstr4(static_cast<
LPCOLESTR>(NULL));
上面的例子中,
bstr1/bstr2
被初始化成長(zhǎng)度為
0
的
BSTR
,也就是說(shuō)
CComBSTR::m_str
是有內(nèi)容的。
bstr3/bstr4
的值被初始化成
NULL
,也就是說(shuō)
CComBSTR::m_str == 0
。這樣,
bstr1/bstr2
在被賦新的值前需要考慮是否需要釋放其中的
BSTR
。
·????????????????????
字符集轉(zhuǎn)換
盡管某些
CComBSTR
方法可以自動(dòng)把
ANSI
字符串轉(zhuǎn)換成
Unicode
。所有的接口返回的都是
Unicode
字符串。如果需要轉(zhuǎn)回
ANSI
,可以使用
ATL
或
MFC
轉(zhuǎn)換類,或者
Windows API
。如果使用文字串修改
CComBSTR
,使用寬字節(jié)字符串。可以減少不必要的轉(zhuǎn)換。例如:
// Declare a CComBSTR object. Although the argument is ANSI,
// the constructor converts it into UNICODE.
CComBSTR bstrMyString( "Hello World" );
// Convert the string into an ANSI string
CW2CT szMyString( bstrMyString );
// Display the ANSI string
MessageBox( NULL, szMyString, _T("String Test"), MB_OK );
?
// The following converts the ANSI string to Unicode
CComBSTR bstr("Test");
// The following uses a Unicode string at compile time
CComBSTR bstr(L"Test");
?
·????????????????????
變量作用域
(Scope)
象所有設(shè)計(jì)完整的類一樣,
CComBSTR
會(huì)在離開(kāi)作用域的時(shí)候釋放資源。如果一個(gè)函數(shù)返回一個(gè)指向
CComBSTR
的指針,可能會(huì)帶來(lái)問(wèn)題:指針有可能指向已經(jīng)被釋放的內(nèi)存。此時(shí)應(yīng)該使用
Copy
或
Detach
方法。參考下面的例子。
HRESULT CMyObject::MyMethod3(/*[out, retval]*/ BSTR* pbstr)
{
??? CComBSTR bstrText(L"Hello");
??? bstrText += " again";
??? *pbstr = bstrText;??????? // No! Call Detach instead!
}
通過(guò)復(fù)制語(yǔ)句
*pbstr = bstrText
,被
bstrText
封裝的
BSTR
的指針作為傳出
[out]
參數(shù)傳遞。在
MyMethod3 return
時(shí),
bstrText
離開(kāi)作用域,
CComBSTR destructor
毀掉用
SysFreeString
釋放這個(gè)
BSTR
。因此,調(diào)用者得到了一個(gè)指向已經(jīng)被釋放的內(nèi)存的指針,可能導(dǎo)致意想不到的結(jié)果。因?yàn)?/span>
bstrText
即將超出作用域,所以必須使用
CComBSTR Copy
或
Detach
給
*pbstr
賦值。
CComBSTR Copy
生成字符串的一格副本,
Detach
簡(jiǎn)單的把
BSTR
移出包裝類。這樣,在
bstrText
離開(kāi)作用域的時(shí)候就不會(huì)被釋放。
HRESULT CMyObject::MyMethod4(/*[out, retval]*/ BSTR* pbstr)
{
??? CComBSTR bstrText(L"Hello");
??? bstrText += L" again";
??? //*pbstr = bstrText.Copy();??? // Better!
??? *pbstr = bstrText.Detach();??? // Much better!
}
在這個(gè)例子中,從效率考慮,最好使用
Detach
而不是
Copy
。
Detach
不需要產(chǎn)生一個(gè)額外副本的開(kāi)銷。當(dāng)
CComBSTR
必須在復(fù)制之后保持自己的內(nèi)容的時(shí)候,例如
CComBSTR
是一個(gè)成員變量,必須使用
Copy
。
·????????????????????
顯式釋放
CComBSTR
內(nèi)容
程序員可以在
CComBSTR
超出作用域范圍前顯示釋放
CComBSTR
中的字符串。一旦釋放了,
CComBSTR
內(nèi)容就無(wú)效了。
CComBSTR
提供了
operator BSTR
,所以代碼中可以顯示的釋放其中的
BSTR
。
HRESULT CMyObject::MyMethod1()
{
CComBSTR bstrText(L"This is a test");
??? ::SysFreeString(bstrText);
// The string will be freed a second time
// when the CComBSTR object goes out of scope,
// which is invalid.
// CComBSTR::Empty() should be used in order to
// explicitly free the BSTR
?
}
在這段代碼中,bstrText 中的BSTR被釋放了。但是,bstrText 仍然沒(méi)有超出作用域,看起來(lái)仍然可以使用。當(dāng)bstrText 最終超出作用域的時(shí)候,SysFreeString 被第二次調(diào)用。為了防止這種意外,需要把operator BSTR 從類中刪除。但這樣沒(méi)有辦法把它用于需要BSTR類型輸入[in]參數(shù)的地方,會(huì)使CComBSTR 幾乎沒(méi)有任何用處。
·????????????????????
外部
CComBSTR
用作
[out]
參數(shù)
把一個(gè)已經(jīng)初始化好的
CComBSTR
的地址傳給一個(gè)函數(shù)作為
[out]
參數(shù)會(huì)導(dǎo)致內(nèi)存泄漏。當(dāng)把
CComBSTR
用于
BSTR*
類型的傳出參數(shù)
[out]
時(shí),必須首先調(diào)用
Empty
方法清空字符串的內(nèi)容。
HRESULT CMyObject::MyMethod2(ISomething* p)
{
??? CComBSTR bstrText;
????
??? bstrText = L"Some assignment";???? // BSTR is allocated.
????
??? bstrText.Empty();????????????????? // Must call empty before
??? pSomething->GetText(&bstrText);??? // using as an [out] parameter.
??? if(bstrText != L"Schaller")
??????? bstrText += "Hello";?????????? // Convert from LPCSTR.
}
在把
CComBSTR
作為
[out]
參數(shù)傳遞前,調(diào)用
Empty
釋必須的。因?yàn)榘凑?/span>
COM
標(biāo)準(zhǔn)中的
[out]
參數(shù)的使用規(guī)則
-
被調(diào)用方法不應(yīng)該在覆蓋
BSTR
的內(nèi)容前調(diào)用
SysFreeString
。如果你忘記調(diào)用
Empty
,調(diào)用前
BSTR
的內(nèi)容占用的資源就會(huì)泄漏。
對(duì)于相同的代碼,如果參數(shù)類型是
[in, out]
,就不會(huì)有泄漏。因?yàn)楹瘮?shù)會(huì)在復(fù)制之前,
Free
原有的串。
·????????????????????
用
CComBSTR
給
BSTR
變量賦值
在下面的代碼中,
CStringTest
使用
CComBSTR
作為成員變量保存
BSTR
屬性。
class CStringTest
{
????
??? CComBSTR m_bstrText;
?
// IStringTest
public:
??? STDMETHOD(put_Text)(/*[in]*/ BSTR newVal)
??? {
??????? m_bstrText = newVal;
??????? return S_OK;
??? }
??? STDMETHOD(get_Text)(/*[out, retval]*/ BSTR *pVal)
??? {
??????? *pVal = m_bstrText;??? // Oops! Call m_bstrText.Copy
?????????????????????????????? // instead.
??????? return S_OK;
??? }
};
由于
m_bstrText
在
get_Text
結(jié)束沒(méi)有超出作用域,你可能認(rèn)為在
the *pVal = m_bstrText
賦值時(shí),不需要調(diào)用
Copy
。這是不對(duì)的。按照
COM
規(guī)則,調(diào)用者負(fù)責(zé)釋放傳出
[out]
參數(shù)的內(nèi)容。由于
*pVal
指向了
m_bstrText
封裝的
BSTR
,而不是一個(gè)副本,調(diào)用者和
m_bstrText
析構(gòu)函數(shù)都會(huì)企圖刪除字符串。
·????????????????????
循環(huán)中使用
CComBSTR Objects
盡管
CComBSTR
可以分配
buffer
完成一些操作,例如:
+= operator
或
Append
。但是,不推薦在一個(gè)小循環(huán)內(nèi)部使用
CComBSTR
完成字符串操作。這種情況下,
CString
能提供更好的性能。
// This is not an efficient way
// to use a CComBSTR object.
CComBSTR bstrMyString;
while (bstrMyString.Length()<1000)
{
?? bstrMyString.Append(L"*");
}
?
_bstr_t
是微軟
C++ COM
擴(kuò)展的一部分。
_bstr_t
封裝了
BSTR
數(shù)據(jù)類型。
_bstr_t
通過(guò)
SysAllocString and SysFreeString
等
BSTR APIs
管理資源的分配和釋放。
_bstr_t
提供了內(nèi)部引用計(jì)數(shù)來(lái)減少額外負(fù)擔(dān)。
Construction
|
Version
|
?
|
_bstr_t
|
?
|
Constructs a _bstr_t object.
|
Operations
|
?
|
?
|
Assign
|
?
|
Copies a BSTR into the BSTR wrapped by a _bstr_t.
|
Attach
|
VC 7
|
Links a _bstr_t wrapper to a BSTR.
|
copy
|
?
|
Constructs a copy of the encapsulated BSTR.
|
Detach
|
VC 7
|
Returns the BSTR wrapped by a _bstr_t and detaches the BSTR from the _bstr_t.
|
GetAddress
|
VC 7
|
Points to the BSTR wrapped by a _bstr_t.
|
GetBSTR
|
VC 7
|
Points to the beginning of the BSTR wrapped by the _bstr_t.
|
length
|
?
|
Returns the number of characters in the _bstr_t.
|
Operators
|
?
|
?
|
operator =
|
?
|
Assigns a new value to an existing _bstr_t object.
|
operator +=
|
?
|
Appends characters to the end of the _bstr_t object.
|
operator +
|
?
|
Concatenates two strings.
|
operator !
|
?
|
Checks if the encapsulated BSTR is a NULL string.
|
operator ==, !=, <, >, <=, >=
|
?
|
Compares two _bstr_t objects.
|
operator wchar_t* | char*
|
?
|
Extract the pointers to the encapsulated Unicode or multibyte BSTR object.
|
?
|
?
|
?
|
?
VC6
中
_bstr_t
缺少了幾個(gè)重要的方法:
Attach/Detach/GetAddress/GetBSTR
,所以比
CComBSTR
簡(jiǎn)單,使得
_bstr_t
的應(yīng)用場(chǎng)合非常有限。而且,
_bstr_t
使用了引用計(jì)數(shù)在不同的對(duì)象間共享
BSTR
,內(nèi)部實(shí)現(xiàn)比
CComBSTR
復(fù)雜。使用注意事項(xiàng)可以參考
CComBSTR
的類似函數(shù)。
建議只用于下面的情況:
·????????????????????
BSTR
的作用域管理
解決
BSTR
變量超出作用域范圍的自動(dòng)回收。
(1)
構(gòu)造簡(jiǎn)單的
BSTR
對(duì)象,對(duì)
BSTR
進(jìn)行基本字符串操作,作為輸入
[in]
參數(shù)傳遞給被調(diào)用者。
{
_bstr_t bs1(L"first ");
??? bs1 += L"second ";
SetBs(bs1); // void SetBs(BSTR bs)
}
?
(2)
作為
BSTR
的
wrapper
,解決
[out]
參數(shù)
BSTR
的生命周期之后的回收問(wèn)題。
HRESULT BetterMethod()
{
??? BSTR val = NULL;
??? GetBs(&val); //void GetBs(/* [out] */ BSTR*)
?
_bstr_t bsVal(val, false);
??? // false is IMPORTANT. Other constructor could
????????? // store the BSTR, too. But you must free the
????????? // BSTR later.
}
?
HRESULT GoodMethod()
{
??? BSTR val = NULL;
??? GetBs(&val); //void GetBs(/* [out] */ BSTR*)
?
// All the function create a copy of BSTR.
// But you must free the BSTR immediately.
?????? ?_bstr_t bsVal2(val);
??????? _bstr_t bsVal3;
??????? bsVal3 = val;
??????? SysFreeString(val);
}
·????????????????????
使用范圍
完成簡(jiǎn)單的BSTR字符串連接、比較等操作。
from:http://blog.csdn.net/pkrobbie/archive/2007/01.aspx
posted on 2007-01-26 16:10
我風(fēng) 閱讀(7173)
評(píng)論(0) 編輯 收藏 引用