CComBSTR を使用したプログラミング
ATL クラス CComBSTR は BSTR のデータ型のラッパーを提供します。CComBSTR が便利なツールですが、注意を必要とするいくつかの状態になります。
変換の問題
範囲の問題
CComBSTR のオブジェクトを明示的に解放できます。
ループの CComBSTR のオブジェクトを使用する
メモリ リークの問題
変換の問題
CComBSTR の複数のメソッドが Unicode に自動的に ANSI 文字列の引数をに変換しますが、メソッドは Unicode 形式の文字列を常に返します。ANSI に、出力文字列を変換するには、ATL 変換クラスを使用します。ATL 変換クラスの詳細については、ATL と MFC の文字列変換マクロを参照してください。
例
// 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
CW2A szMyString(bstrMyString);
// Display the ANSI string
MessageBoxA(NULL, szMyString, "String Test", MB_OK);
CComBSTR のオブジェクトを変更する場合にリテラル文字列を使用する場合はワイド文字列を使用します。これは、不要な変換が低くなります。
例
// The following converts the ANSI string to Unicode
CComBSTR bstr1("Test");
// The following uses a Unicode string at compile time
CComBSTR bstr2(L"Test");
範囲の問題
すべての行儀が、クラスと同様に、CComBSTR がスコープ外に出るとリソースを解放します。関数が CComBSTR の文字列へのポインターを返す場合、これは、ポインターが既に解放されているメモリを参照すると問題ができます。このような場合、次に示すように [コピー] のメソッドを使用します。
例
// The wrong way to do it
BSTR * MyBadFunction()
{
// Create the CComBSTR object
CComBSTR bstrString(L"Hello World");
// Convert the string to uppercase
HRESULT hr;
hr = bstrString.ToUpper();
// Return a pointer to the BSTR. ** Bad thing to do **
return &bstrString;
}
// The correct way to do it
HRESULT MyGoodFunction(/*[out]*/ BSTR* bstrStringPtr)
{
// Create the CComBSTR object
CComBSTR bstrString(L"Hello World");
// Convert the string to uppercase
HRESULT hr;
hr = bstrString.ToUpper();
if (hr != S_OK)
return hr;
// Return a copy of the string.
return bstrString.CopyTo(bstrStringPtr);
}
CComBSTR のオブジェクトを明示的に解放できます。
オブジェクトがスコープ外になる前に明示的に CComBSTR のオブジェクトに含まれる文字列を解放することはできます。文字列がリリースされた場合は、CComBSTR のオブジェクトは無効です。
例
// Declare a CComBSTR object
CComBSTR bstrMyString(L"Hello World");
// Free the string explicitly
::SysFreeString(bstrMyString);
// The string will be freed a second time
// when the CComBSTR object goes out of scope,
// which is invalid.
ループの CComBSTR のオブジェクトを使用する
特定の操作を、[追加] の += の演算子やメソッドなどの実行するに CComBSTR のクラスがバッファーを割り当てるため、短いループ内の文字列操作を実行することはお勧めできません。この場合、CStringT は、より優れたパフォーマンスを実現します。
例
// This is not an efficient way to use a CComBSTR object.
CComBSTR bstrMyString;
HRESULT hr;
while (bstrMyString.Length() < 1000)
hr = bstrMyString.Append(L"*");
メモリ リークの問題
[out] のパラメーターとして関数に初期化された CComBSTR のアドレスを渡すと、メモリ リークが発生します。
次の例では、文字列 "Initialized" を保持するために割り当てる文字列は、関数 MyGoodFunction が文字列を置き換える場合漏ります。
CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);
リークを回避するには、[out] のアドレスをパラメーターとして渡す前に CComBSTR のあるオブジェクトの [空] のメソッドを呼び出します。
関数パラメーターが **[in, out]**同じコードがリークが発生しないことに注意してください。