Sémantique de pile C++ pour les types référence
Avant Visual C++ 2005, une instance d'un type référence peut être créée à l'aide de l'opérateur d' new, qui a créé l'objet sur le tas récupéré par le garbage collector.Toutefois, vous pouvez à présent créer une instance d'un type référence à la même syntaxe que vous utiliserez pour créer une instance d'un type natif sur la pile.Ainsi, vous n'avez pas besoin d'utiliser ref new, gcnew (extensions du composant C++) pour créer un objet d'un type référence.Et lorsque l'objet est hors de portée, le compilateur appelle le destructeur de l'objet.
Remarques
Lorsque vous créez une instance d'un type référence à l'aide de la sémantique de pile, le compilateur crée en interne l'instance sur le tas récupéré par le garbage collector (à l'aide de gcnew).
Lorsque la signature ou le type de retour d'une fonction comprend une instance d'un type référence par valeur, la fonction est marquée dans les métadonnées comme spécification de la gestion spéciale (avec le modreq).Cette gestion spéciale actuel n'est fournie par les clients Visual C++ ; d'autres langages ne prennent actuellement pas consommer des fonctions ou des données qui utilisent des types référence créés avec la sémantique de pile.
Une raison d'utiliser gcnew (allocation dynamique) au lieu de la sémantique de pile serait si le type n'a aucun destructeur.En outre, l'utilisation de types référence créés avec la sémantique de pile dans les signatures de la fonction ne sont pas possible si vous souhaitez que vos fonctions à utiliser par les langages autres que Visual C++.
Le compilateur ne génère pas de constructeur de copie pour un type référence.Par conséquent, si vous définissez une fonction qui utilise un type référence en fonction de la valeur dans la signature, vous devez définir un constructeur de copie pour un type référence.Un constructeur de copie pour un type référence a une signature de la forme suivante : R(R%){}.
Le compilateur ne génère pas d'opérateur d'assignation par défaut pour un type référence.Un opérateur d'assignation vous permet de créer un objet à l'aide de la sémantique de pile et l'initialisation à un objet existant créé à l'aide de la sémantique de pile.Un opérateur d'assignation pour un type référence a une signature de la forme suivante : void operator=( R% ){}.
Si le destructeur de votre type libère les ressources critiques et vous sémantique de pile d'utilisation pour les types référence, vous n'avez pas besoin d'appeler explicitement le destructeur (ou appeler delete).Pour plus d'informations sur les destructeurs dans les types référence, consultez Destructeurs et finaliseurs dans Visual C++.
Un opérateur d'assignation généré par le compilateur suivra classiques les règles de la norme C++ avec les ajouts suivants :
Toutes les données membres non statiques dont le type est un handle vers un type référence superficielles sont copiées (traitée comme une donnée membre non static dont le type est un pointeur).
Toute donnée membre non static dont le type est un type valeur sera superficielle copiée.
Toute donnée membre non static dont le type est une instance d'un type référence appelle un appel au constructeur de copie de type référence.
Le compilateur fournit également un opérateur unaire d' % pour convertir une instance d'un type référence créé à l'aide de la sémantique de pile à son type sous-jacent de handle.
Les types référence suivants sont pas disponibles pour être utilisés avec la sémantique de pile :
Exemple
Description
L'exemple de code suivant montre comment déclarer des instances des types référence à la sémantique de pile, comment l'opérateur d'assignation et le constructeur de copie fonctionne, et comment initialiser une référence de suivi au type référence créé à l'aide de la sémantique de pile.
Code
// stack_semantics_for_reference_types.cpp
// compile with: /clr
ref class R {
public:
int i;
R(){}
// assignment operator
void operator=(R% r) {
i = r.i;
}
// copy constructor
R(R% r) : i(r.i) {}
};
void Test(R r) {} // requires copy constructor
int main() {
R r1;
r1.i = 98;
R r2(r1); // requires copy constructor
System::Console::WriteLine(r1.i);
System::Console::WriteLine(r2.i);
// use % unary operator to convert instance using stack semantics
// to its underlying handle
R ^ r3 = %r1;
System::Console::WriteLine(r3->i);
Test(r1);
R r4;
R r5;
r5.i = 13;
r4 = r5; // requires a user-defined assignment operator
System::Console::WriteLine(r4.i);
// initialize tracking reference
R % r6 = r4;
System::Console::WriteLine(r6.i);
}
Sortie
98
98
98
13
13