C++-Stack-Semantik für Referenztypen
Vor Visual Studio 2005 konnte eine Instanz eines Verweistyps nur mithilfe des Operators erstellt werden, der new
das Objekt für den garbage collection heap erstellt hat. Sie können nun jedoch eine Instanz eines Verweistyps mit derselben Syntax erstellen, die Sie zum Erstellen einer Instanz eines systemeigenen Typs im Stapel verwenden würden. Daher müssen Sie ref new, gcnew nicht verwenden, um ein Objekt eines Verweistyps zu erstellen. Und wenn das Objekt außerhalb des Gültigkeitsbereichs liegt, ruft der Compiler den Destruktor des Objekts auf.
Hinweise
Wenn Sie eine Instanz eines Referenztyps mithilfe der Stapelsemantik erstellen, erstellt der Compiler intern die Instanz für den garbage collection heap (using gcnew
).
Wenn die Signatur oder der Rückgabetyp einer Funktion eine Instanz eines Nachwertverweistyps enthält, wird die Funktion in den Metadaten als spezielle Behandlung (mit Modreq) gekennzeichnet. Diese spezielle Behandlung wird derzeit nur von Visual C++-Clients bereitgestellt. Andere Sprachen unterstützen derzeit nicht die Verwendung von Funktionen oder Daten, die mit Stapelsemantik erstellte Referenztypen verwenden.
Ein Grund für die Verwendung gcnew
(dynamische Zuordnung) anstelle der Stapelsemantik wäre, wenn der Typ keinen Destruktor aufweist. Außerdem wäre die Verwendung von Verweistypen, die mit Stapelsemantik in Funktionssignaturen erstellt wurden, nicht möglich, wenn Ihre Funktionen von anderen Sprachen als Visual C++ verwendet werden sollen.
Der Compiler generiert keinen Kopierkonstruktor für einen Verweistyp. Wenn Sie also eine Funktion definieren, die einen Nachwertverweistyp in der Signatur verwendet, müssen Sie einen Kopierkonstruktor für den Referenztyp definieren. Ein Kopierkonstruktor für einen Verweistyp weist eine Signatur des folgenden Formulars auf: R(R%){}
Der Compiler generiert keinen Standardzuweisungsoperator für einen Verweistyp. Mit einem Zuordnungsoperator können Sie ein Objekt mithilfe von Stapelsemantik erstellen und mit einem vorhandenen Objekt initialisieren, das mit Stapelsemantik erstellt wurde. Ein Zuordnungsoperator für einen Verweistyp weist eine Signatur des folgenden Formulars auf: void operator=( R% ){}
Wenn der Destruktor ihres Typs kritische Ressourcen freigibt und Sie Stapelsemantik für Referenztypen verwenden, müssen Sie den Destruktor (oder Aufruf delete
) nicht explizit aufrufen. Weitere Informationen zu Destruktoren in Referenztypen finden Sie unter Destruktoren und Finalizer in How to: Define and consume classes and structs (C++/CLI).
Ein vom Compiler generierter Zuordnungsoperator folgt den üblichen C++-Standardregeln mit den folgenden Ergänzungen:
Alle nicht statischen Datenmember, deren Typ ein Handle für einen Verweistyp ist, werden flach kopiert (behandelt wie ein nicht statisches Datenmember, dessen Typ ein Zeiger ist).
Alle nicht statischen Datenmemembe, deren Typ ein Werttyp ist, werden flach kopiert.
Alle nicht statischen Datenmemmemm, deren Typ eine Instanz eines Verweistyps ist, rufen einen Aufruf des Kopierkonstruktors des Verweistyps auf.
Der Compiler stellt außerdem einen %
unären Operator bereit, um eine Instanz eines Referenztyps zu konvertieren, der mithilfe von Stapelsemantik in den zugrunde liegenden Handletyp erstellt wurde.
Die folgenden Referenztypen sind für die Verwendung mit Stapelsemantik nicht verfügbar:
Beispiel
Beschreibung
Im folgenden Codebeispiel wird gezeigt, wie Instanzen von Verweistypen mit Stapelsemantik deklariert werden, wie der Zuordnungsoperator und Kopierkonstruktor funktioniert und wie sie einen Nachverfolgungsverweis mit Verweistyp initialisieren, der mithilfe von Stapelsemantik erstellt wurde.
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);
}
Output
98
98
98
13
13