次の方法で共有


CComBSTR を使用したプログラミング

更新 : 2007 年 11 月

ATL クラス CComBSTR は、BSTR データ型を扱うラッパーを提供します。CComBSTR は便利ですが、次の場合は注意が必要です。

  • 変換の問題

  • スコープの問題

  • CComBSTR オブジェクトの明示的な解放

  • ループでの CComBSTR オブジェクトの使用

  • メモリ リークの問題

変換の問題

CComBSTR のいくつかのメソッドでは、ANSI 文字列の引数が自動的に Unicode に変換されますが、常に 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 文字列へのポインタを返す場合は、ポインタが既に解放されたメモリを参照するため、問題が発生する可能性があります。この場合は、次のように Copy メソッドを使用します。

// 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 クラスでは、+= 演算子や Append メソッドなどの特定の操作の実行時にバッファを割り当てるため、ループでは文字列を操作しないことをお勧めします。このような場合は CStringT を使用するとパフォーマンスが向上します。

// This is not an efficient way to use a CComBSTR object.
CComBSTR bstrMyString;
HRESULT hr;
while (bstrMyString.Length() < 1000)
   hr = bstrMyString.Append(L"*");   

メモリ リークの問題

初期化された CComBSTR のアドレスを [out] パラメータとして関数に渡すと、メモリ リークが発生します。

次の例で、"Initialized" を保持するように割り当てられた文字列は、MyGoodFunction 関数がこの文字列を置換したときにリークします。

CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);   

リークを防ぐには、アドレスを [out] パラメータとして渡す前に、既存の CComBSTR オブジェクトで Empty メソッドを呼び出します。

関数のパラメータが [in, out] の場合、同じコードでもリークは発生しません。

参照

参照

CStringT クラス

wstring

その他の技術情報

ATL の概念

文字列変換に関するマクロ