Udostępnij za pośrednictwem


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].

Zobacz też

Pojęcia
CStringT, klasa
wciąg
Makra konwersji ciągów