Программирование с использованием CComBSTR (ATL)

Класс ATL CComBSTR предоставляет оболочку вокруг типа данных BSTR . Хотя CComBSTR это полезное средство, существует несколько ситуаций, требующих осторожности.

Проблемы с преобразованием

Хотя несколько CComBSTR методов автоматически преобразуют строковый аргумент ANSI в Юникод, методы всегда возвращают строки формата Юникода. Чтобы преобразовать выходную строку обратно в 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);   

Чтобы избежать утечки, вызовите Empty метод для существующих CComBSTR объектов перед передачей адреса в качестве параметра [out] .

Обратите внимание, что тот же код не приведет к утечке, если параметр функции был [в,out].

См. также

Основные понятия
Класс CStringT
wstring
Макросы преобразования строк