Programmation avec CComBSTR
La classe CComBSTR ATL fournit un wrapper autour de le type de données d' BSTR .Pendant qu' CComBSTR est un outil utile, il existe plusieurs situations qui requièrent l'avertissement.
Problèmes de conversion
Problèmes de portée
Libérer explicitement l'objet de CComBSTR
À l'aide de objets de CComBSTR dans les boucles
Problèmes de fuite de mémoire
Problèmes de conversion
Bien que plusieurs méthodes d' CComBSTR convertissent automatiquement un argument de chaîne ANSI dans Unicode, les méthodes retournent toujours les chaînes au format Unicode.Pour convertir la chaîne de sortie vers ANSI, utilisez une classe de conversion ATL.Pour plus d'informations sur les classes de conversion ATL, consultez Macros de conversion de chaînes ATL et MFC.
Exemple
// 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);
Si vous utilisez un littéral de chaîne pour modifier un objet d' CComBSTR , utilisez des chaînes à caractères larges.Cela réduira des conversions inutiles.
Exemple
// The following converts the ANSI string to Unicode
CComBSTR bstr1("Test");
// The following uses a Unicode string at compile time
CComBSTR bstr2(L"Test");
Problèmes de portée
Comme avec n'importe quelle classe polie, CComBSTR libère les ressources lorsqu'il est hors de portée.Si une fonction retourne un pointeur vers la chaîne d' CComBSTR , cela peut provoquer des problèmes, car le pointeur référence la mémoire qui a déjà été libérée.Dans ces cas, utilisez la méthode de Copier , comme indiqué ci-dessous.
Exemple
// 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);
}
Libérer explicitement l'objet de CComBSTR
Il est possible de libérer explicitement la chaîne contenue dans l'objet d' CComBSTR avant que l'objet afin portée.Si la chaîne est libérée, l'objet d' CComBSTR est incorrect.
Exemple
// 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.
À l'aide de objets de CComBSTR dans les boucles
Comme la classe d' CComBSTR alloue une mémoire tampon afin d'exécuter certaines opérations, telles que l'opérateur d' += ou la méthode de Ajouter , il n'est pas recommandé d'exécuter la manipulation de chaînes dans une boucle serrée.Dans ces situations, CStringT offre de meilleures performances.
Exemple
// This is not an efficient way to use a CComBSTR object.
CComBSTR bstrMyString;
HRESULT hr;
while (bstrMyString.Length() < 1000)
hr = bstrMyString.Append(L"*");
Problèmes de fuite de mémoire
Obtenir l'adresse d' CComBSTR initialisé à une fonction comme paramètre de [out] provoque une fuite de mémoire.
Dans l'exemple ci-dessous, la chaîne allouée pour contenir la chaîne "Initialized" est coulée lorsque la fonction MyGoodFunction remplace la chaîne.
CComBSTR bstrLeak(L"Initialized");
HRESULT hr = MyGoodFunction(&bstrLeak);
Pour éviter une fuite, appelez la méthode de Vide exister sur des objets d' CComBSTR avant de passer l'adresse comme paramètre de [out] .
Notez que le même code ne provoquerait pas une fuite si le paramètre de la fonction était [in, out].