Programowanie przy użyciu CComBSTR (ALT)
Klasa ATL CComBSTR zapewnia otokę wokół typu danych BSTR. Chociaż CComBSTR
jest to przydatne narzędzie, istnieje kilka sytuacji, które wymagają ostrożności.
Problemy z konwersją
Chociaż kilka CComBSTR
metod automatycznie konwertuje argument ciągu ANSI na Unicode, metody zawsze zwracają ciągi formatu Unicode. Aby przekonwertować ciąg wyjściowy z powrotem na ANSI, użyj klasy konwersji ATL. Aby uzyskać więcej informacji na temat klas konwersji ATL, zobacz AtL i MFC String Conversion Macros (Makra konwersji ciągów ATL i MFC).
Przykład
// 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);
Jeśli używasz literału ciągu do modyfikowania CComBSTR
obiektu, użyj ciągów znaków szerokich, aby zmniejszyć niepotrzebne konwersje.
// The following converts the ANSI string to Unicode
CComBSTR bstr1("Test");
// The following uses a Unicode string at compile time
CComBSTR bstr2(L"Test");
Problemy z zakresem
Podobnie jak w przypadku każdej dobrze zachowywanej klasy, CComBSTR
zwalnia zasoby, gdy wykracza poza zakres. Jeśli funkcja zwróci wskaźnik do ciągu, może to spowodować problemy, ponieważ wskaźnik odwołuje się do CComBSTR
pamięci, która została już zwolniona. W takich przypadkach użyj Copy
metody , jak pokazano poniżej.
Przykład
// 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);
}
Jawne zwalnianie obiektu CComBSTR
Istnieje możliwość jawnego zwolnienia ciągu zawartego CComBSTR
w obiekcie przed wyjściem zakresu obiektu. Jeśli ciąg zostanie zwolniony, CComBSTR
obiekt jest nieprawidłowy.
Przykład
// 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.
Używanie obiektów CComBSTR w pętlach
CComBSTR
Ponieważ klasa przydziela bufor do wykonywania niektórych operacji, takich jak +=
operator lub Append
metoda, nie zaleca się wykonywania manipulowania ciągami wewnątrz ciasnej pętli. W takich sytuacjach CStringT
zapewnia lepszą wydajność.
Przykład
// This is not an efficient way to use a CComBSTR object.
CComBSTR bstrMyString;
HRESULT hr;
while (bstrMyString.Length() < 1000)
hr = bstrMyString.Append(L"*");
Problemy z przeciekiem pamięci
Przekazanie adresu zainicjowanego CComBSTR
do funkcji jako parametru [out] powoduje wyciek pamięci.
W poniższym przykładzie ciąg przydzielony do przechowywania ciągu "Initialized"
jest wyciekany, gdy funkcja MyGoodFunction
zastępuje ciąg.
CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);
Aby uniknąć wycieku, przed przekazaniem adresu jako parametru [out] wywołaj Empty
metodę dla istniejących CComBSTR
obiektów.
Należy pamiętać, że ten sam kod nie spowoduje wycieku, jeśli parametr funkcji był [w, out].