使用 CComBSTR 进行编程 (ATL)

ATL 类 CComBSTR 提供了围绕 BSTR 数据类型的包装。 虽然 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] 参数传递将导致内存泄露。

在下面的示例中,当函数 MyGoodFunction 替换字符串时,分配给保存字符串 "Initialized" 的字符串将泄漏。

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

若要避免泄漏,请在将 Empty 地址作为[out]参数传递之前对现有 CComBSTR 对象调用方法。

请注意,如果函数的参数为 [in,out],则相同的代码不会导致泄漏。

请参阅

概念
CStringT 类
wstring
字符串转换宏