使用 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);   

为了避免泄漏,请先对现有 CComBSTR 对象调用 Empty 方法,然后再将地址作为 [out] 参数传递。

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

另请参阅

概念
CStringT 类
wstring
字符串转换宏