Программирование с использованием 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
Макросы преобразования строк