编程时CComBSTR

ATL选件类 CComBSTRBSTR 数据类型的提供包装。 当 CComBSTR 非常有用的工具时,有需要注意的几种情况。

  • 转换问题

  • 范围问题

  • 显式释放CComBSTR对象

  • 在循环中使用CComBSTR Objects

  • 内存泄漏问题

转换问题

虽然多个 CComBSTR 方法将自动转换为ANSI字符串参数转换为Unicode,方法将总是返回Unicode格式字符串。 若要将输出字符串返回ANSI,请使用ATL转换选件类。 有关ATL转换选件类的更多信息,请参见 ATL和MFC字符串翻译宏

bdyd6xz6.collapse_all(zh-cn,VS.110).gif示例

// 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 对象,请使用宽字符字符串。 这将减少不必要的转换。

bdyd6xz6.collapse_all(zh-cn,VS.110).gif示例

// 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 方法,如下所示。

bdyd6xz6.collapse_all(zh-cn,VS.110).gif示例

// 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 对象无效。

bdyd6xz6.collapse_all(zh-cn,VS.110).gif示例

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

因为 CComBSTR 选件类分配缓冲区执行特定操作,例如 += 运算符或 Append 方法,建议不要对一个紧凑循环中的字符串操作。 在这些情况下,CStringT 提供更好的性能。

bdyd6xz6.collapse_all(zh-cn,VS.110).gif示例

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

其他资源

ATL概念

字符串翻译宏