Programando com o CComBSTR (ATL)

A classe ATL CComBSTR fornece um wrapper em torno do tipo de dados BSTR. Embora CComBSTR seja uma ferramenta útil, há várias situações que exigem cautela.

Problemas de conversão

Embora vários métodos CComBSTR convertam automaticamente um argumento de cadeia de caracteres ANSI em Unicode, os métodos sempre retornarão cadeias de caracteres de formato Unicode. Para converter a cadeia de caracteres de saída de volta em ANSI, use uma classe de conversão ATL. Para obter mais informações sobre as classes de conversão ATL, confira Macros de conversão de cadeia de caracteres ATL e MFC.

Exemplo

// 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);   

Se você estiver usando um literal de cadeia de caracteres para modificar um objeto CComBSTR, use cadeias de caracteres largos para reduzir conversões desnecessárias.

// The following converts the ANSI string to Unicode
CComBSTR bstr1("Test");
// The following uses a Unicode string at compile time 
CComBSTR bstr2(L"Test");   

Problemas de escopo

Assim como acontece com qualquer classe bem comportada, CComBSTR liberará seus recursos quando ela sair do escopo. Se uma função retornar um ponteiro para a cadeia de caracteres CComBSTR, isso poderá causar problemas, pois o ponteiro fará referência à memória que já foi liberada. Nesses casos, use o método Copy, conforme mostrado abaixo.

Exemplo

// 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);
}

Liberar explicitamente o objeto CComBSTR

É possível liberar explicitamente a cadeia de caracteres contida no objeto CComBSTR antes que o objeto saia do escopo. Se a cadeia de caracteres for liberada, o objeto CComBSTR será inválido.

Exemplo

// 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.   

Usar objetos CComBSTR em loops

Como a classe CComBSTR aloca um buffer para executar determinadas operações, como o operador += ou o método Append, não é recomendável que você execute a manipulação de cadeia de caracteres dentro de um loop apertado. Nessas situações, CStringT fornece melhor desempenho.

Exemplo

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

Problemas de perda de memória

Passar o endereço de um CComBSTR inicializado para uma função como um parâmetro [out] causa uma perda de memória.

No exemplo abaixo, a cadeia de caracteres alocada para manter a cadeia de caracteres "Initialized" é vazada quando a função MyGoodFunction substitui a cadeia de caracteres.

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

Para evitar a perda, chame o método Empty em objetos CComBSTR existentes antes de passar o endereço como um parâmetro [out].

Observe que o mesmo código não causaria uma perda se o parâmetro da função fosse [in, out].

Confira também

Conceitos
Classe CStringT
wstring
Macros de conversão de cadeia de caracteres