Programmazione con CComBSTR
La classe CComBSTR ATL fornisce un wrapper del tipo di dati BSTR.Mentre CComBSTR è uno strumento utile, esistono diverse situazioni che richiedono una particolare attenzione.
Problemi di conversione
Problemi di ambito
Liberare in modo esplicito l'oggetto di CComBSTR
Utilizzo di oggetti di CComBSTR nei cicli
Problemi di perdita di memoria
Problemi di conversione
Sebbene diversi metodi CComBSTR automaticamente convertano un argomento stringa ANSI in Unicode, i metodi restituiscono sempre le stringhe di formato Unicode.Per convertire la stringa di output dell'ANSI, utilizzare una classe di conversione ATL.Per ulteriori informazioni sulle classi di conversione ATL, vedere Macro per la conversione delle stringhe MFC e ATL.
Esempio
// 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);
Se si utilizza un valore letterale stringa per modificare un oggetto CComBSTR, utilizzare le stringhe di caratteri estesi.Riducendo in questo modo le conversioni non necessari.
Esempio
// The following converts the ANSI string to Unicode
CComBSTR bstr1("Test");
// The following uses a Unicode string at compile time
CComBSTR bstr2(L"Test");
Problemi di ambito
Come con qualsiasi classe garbata, CComBSTR libererà le risorse quando esce dall'ambito.Se una funzione restituisce un puntatore alla stringa CComBSTR, questa può causare problemi, poiché il puntatore farà riferimento a memoria che è già stata liberata.In questi casi, utilizzare il metodo Copia, come illustrato di seguito.
Esempio
// 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);
}
Liberare in modo esplicito l'oggetto di CComBSTR
Viene esplicitamente formato della stringa contenuta nell'oggetto CComBSTR prima dell'oggetto uscire dall'ambito.Se la stringa viene liberata, l'oggetto CComBSTR non è valido.
Esempio
// 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.
Utilizzo di oggetti di CComBSTR nei cicli
Poiché la classe CComBSTR alloca un buffer per eseguire determinate operazioni, come operatore += o il metodo Append, non è consigliabile eseguire la modifica delle stringhe in un ciclo rigido.In queste situazioni, CStringT offre prestazioni migliori.
Esempio
// This is not an efficient way to use a CComBSTR object.
CComBSTR bstrMyString;
HRESULT hr;
while (bstrMyString.Length() < 1000)
hr = bstrMyString.Append(L"*");
Problemi di perdita di memoria
Passando l'indirizzo CComBSTR inizializzato a una funzione come parametro [out] causa una perdita di memoria.
Nell'esempio riportato di seguito, la stringa allocata per contenere la stringa "Initialized" è cast quando la funzione MyGoodFunction sostituisce la stringa.
CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);
Per evitare la perdita, chiamare il metodo Empty gli oggetti esistenti CComBSTR prima di passare all'indirizzo come parametro [out].
Si noti che lo stesso codice non può provocare una perdita se il parametro di funzione è [in, out].