Handle sur l'opérateur Object (^) (extensions du composant C++)
Les déclarateurs de handle (^, prononcé « chapeau »), modifie le type spécificateur pour indiquer que l'objet déclaré doit être supprimé automatiquement lorsque le système détermine que l'objet n'est plus accessible.
Accès de l'objet déclaré
Une variable déclarée avec les déclarateurs de handle se comporte comme un pointeur vers l'objet.Toutefois, la variable pointe vers l'objet entier, ne peuvent pas désigner un membre de l'objet, et il ne prend pas en charge les opérations arithmétiques sur les pointeurs.Utilisez l'opérateur d'indirection (*) pour accéder à l'objet, et l'opérateur d'accès de membre de flèche (->) pour accéder à un membre de l'objet.
Windows Runtime
Le compilateur utilise le mécanisme de décompte de références COM pour déterminer si l'objet est plus utilisé et ne peut être supprimé.C'est possible parce qu'un objet dérivé d'une interface d'exécution windows est en fait un objet COM.Le décompte de références est incrémenté lorsque l'objet est créé ou copié, et est décrémenté lorsque l'objet est défini pour annuler ou hors de portée.Si le décompte de références accède à zéro, l'objet automatiquement et immédiatement est supprimé.
L'avantage du déclarateurs de handle est que dans COM que vous devez gérer explicitement le décompte de références pour un objet, qui est un processus fastidieuse et sujet aux erreurs.Autrement dit, pour incrémenter ou décrémenter le décompte de références vous devez appeler les méthodes d'AddRef() et de Release() de l'objet.Toutefois, si vous déclarez un objet avec les déclarateurs de handle, le compilateur Visual C++ génère du code qui ajuste automatiquement le décompte de références.
Pour des informations sur la façon d'instancier un objet, consultez nouvelle référence.
Configuration requise
Option du compilateur : /ZW
Common Language Runtime
Le système utilise le mécanisme de garbage collector du CLR pour déterminer si l'objet est plus utilisé et ne peut être supprimé.Le common langage runtime gère un tas sur lequel il alloue des objets, et utilise des références managées (variables) dans votre programme indiquent l'emplacement des objets sur le tas.Lorsqu'un objet n'est plus utilisé, la mémoire qu'il a occupée sur le tas est libérée.Périodiquement, le garbage collector condense le tas pour mieux utiliser la mémoire libérée.Compacter le tas peut déplacer des objets sur le tas, qui invalide les emplacements référencés par des références managées.Toutefois, le garbage collector s'aperçoit de l'emplacement de toutes les références managées, et les met à jour automatiquement pour indiquer la position actuelle des objets sur le tas.
Étant donné que les pointeurs natifs C++ (*) et les références (&) ne sont pas des références gérées, le garbage collector ne peut pas mettre à jour automatiquement les adresses qu'ils pointent vers.Pour résoudre ce problème, utilisez les déclarateurs de handle pour spécifier une variable que le garbage collector s'aperçoit de et peut mettre à jour automatiquement.
Dans Visual C++ 2002 et Visual C++ 2003, __gc * a été utilisé pour déclarer un objet sur le tas managé.^ remplace __gc * dans la nouvelle syntaxe.
Pour plus d'informations, consultez Comment : déclarer des handles dans les types natifs.
Exemples
Exemple
Cet exemple montre comment créer une instance d'un type référence sur le tas managé.Cet exemple montre également que vous pouvez initialiser un handle avec un autre, ce qui peut provoquer deux références au même objet sur le tas managé et récupéré par le garbage collector.Notez que d'assigner nullptr (extensions du composant C++) à un handle ne marque pas l'objet pour le garbage collection.
// mcppv2_handle.cpp
// compile with: /clr
ref class MyClass {
public:
MyClass() : i(){}
int i;
void Test() {
i++;
System::Console::WriteLine(i);
}
};
int main() {
MyClass ^ p_MyClass = gcnew MyClass;
p_MyClass->Test();
MyClass ^ p_MyClass2;
p_MyClass2 = p_MyClass;
p_MyClass = nullptr;
p_MyClass2->Test();
}
Sortie
Exemple
L'exemple suivant indique comment déclarer un handle vers un objet sur le tas managé, où le type d'objet est un type valeur boxed.l'exemple montre également comment obtenir le type valeur de l'objet boxed.
// mcppv2_handle_2.cpp
// compile with: /clr
using namespace System;
void Test(Object^ o) {
Int32^ i = dynamic_cast<Int32^>(o);
if(i)
Console::WriteLine(i);
else
Console::WriteLine("Not a boxed int");
}
int main() {
String^ str = "test";
Test(str);
int n = 100;
Test(n);
}
Sortie
Exemple
Cet exemple montre que l'idiome de commune C++ d'utiliser un pointeur de type void* pour indiquer un objet arbitraire est remplacé par Object^, qui peut contenir un handle à toute classe de référence.Il montre également que tous les types, tels que des tableaux et des délégués, peut être converti en un handle d'objet.
// mcppv2_handle_3.cpp
// compile with: /clr
using namespace System;
using namespace System::Collections;
public delegate void MyDel();
ref class MyClass {
public:
void Test() {}
};
void Test(Object ^ x) {
Console::WriteLine("Type is {0}", x->GetType());
}
int main() {
// handle to Object can hold any ref type
Object ^ h_MyClass = gcnew MyClass;
ArrayList ^ arr = gcnew ArrayList();
arr->Add(gcnew MyClass);
h_MyClass = dynamic_cast<MyClass ^>(arr[0]);
Test(arr);
Int32 ^ bi = 1;
Test(bi);
MyClass ^ h_MyClass2 = gcnew MyClass;
MyDel^ DelInst = gcnew MyDel(h_MyClass2, &MyClass::Test);
Test(DelInst);
}
Sortie
Exemple
Cet exemple indique qu'un handle peut être déréférencé et qu'un membre est accessible via un handle en cours de suppression.
// mcppv2_handle_4.cpp
// compile with: /clr
using namespace System;
value struct DataCollection {
private:
int Size;
array<String^>^ x;
public:
DataCollection(int i) : Size(i) {
x = gcnew array<String^>(Size);
for (int i = 0 ; i < Size ; i++)
x[i] = i.ToString();
}
void f(int Item) {
if (Item >= Size)
{
System::Console::WriteLine("Cannot access array element {0}, size is {1}", Item, Size);
return;
}
else
System::Console::WriteLine("Array value: {0}", x[Item]);
}
};
void f(DataCollection y, int Item) {
y.f(Item);
}
int main() {
DataCollection ^ a = gcnew DataCollection(10);
f(*a, 7); // dereference a handle, return handle's object
(*a).f(11); // access member via dereferenced handle
}
Sortie
Exemple
Cet exemple montre qu'une référence native (&) ne peut pas la lier à un membre d' int d'un type managé, comme int peut être enregistré dans le tas récupéré par le garbage collector, et les références natives ne suivent pas le déplacement d'objets dans le tas managé.Le correctif est d'utiliser une variable locale, ou de modifier & à %, pour en faire une référence de suivi.
// mcppv2_handle_5.cpp
// compile with: /clr
ref struct A {
void Test(unsigned int &){}
void Test2(unsigned int %){}
unsigned int i;
};
int main() {
A a;
a.i = 9;
a.Test(a.i); // C2664
a.Test2(a.i); // OK
unsigned int j = 0;
a.Test(j); // OK
}
Configuration requise
Option du compilateur : /clr
Voir aussi
Référence
Opérateur de référence de suivi (extensions du composant C++)