C++ – sémantika zásobníku pro odkazové typy
Před sadou Visual Studio 2005 bylo možné vytvořit instanci referenčního typu pouze pomocí operátoru new
, který vytvořil objekt v haldě s uvolňováním paměti. Teď ale můžete vytvořit instanci referenčního typu pomocí stejné syntaxe, jakou byste použili k vytvoření instance nativního typu v zásobníku. Proto není nutné použít odkaz nový, gcnew k vytvoření objektu typu odkazu. A když objekt přestane být obor, kompilátor volá destruktor objektu.
Poznámky
Když vytvoříte instanci referenčního typu pomocí sémantiky zásobníku, kompilátor interně vytvoří instanci na haldě s uvolňováním paměti (pomocí gcnew
).
Pokud podpis nebo návratový typ funkce obsahuje instanci typu odkazu podle hodnoty, bude funkce označena v metadatech jako vyžadování speciálního zpracování (s modreq). Toto speciální zpracování v současné době poskytuje pouze klienti Jazyka Visual C++; jiné jazyky v současné době nepodporují využívání funkcí nebo dat, které používají referenční typy vytvořené sémantikou zásobníku.
Jedním z důvodů použití gcnew
(dynamické přidělování) místo sémantiky zásobníku by bylo, kdyby typ neměl žádný destruktor. Použití referenčních typů vytvořených s sémantikou zásobníku v podpisech funkcí by také nebylo možné, pokud chcete, aby vaše funkce používaly jiné jazyky než Visual C++.
Kompilátor nevygeneruje konstruktor kopírování pro typ odkazu. Proto pokud definujete funkci, která v podpisu používá typ odkazu podle hodnoty, je nutné definovat konstruktor kopírování pro typ odkazu. Konstruktor kopie pro typ odkazu má podpis následující formuláře: R(R%){}
.
Kompilátor negeneruje výchozí operátor přiřazení pro typ odkazu. Operátor přiřazení umožňuje vytvořit objekt pomocí sémantiky zásobníku a inicializovat ho pomocí existujícího objektu vytvořeného pomocí sémantiky zásobníku. Operátor přiřazení pro typ odkazu má podpis následujícího formuláře: void operator=( R% ){}
.
Pokud destruktor vašeho typu uvolní kritické prostředky a použijete sémantika zásobníku pro odkazové typy, nemusíte explicitně volat destruktor (nebo volání delete
). Další informace o destruktory v referenčních typech naleznete v tématu Destruktory a finalizátory v tématu Postupy: Definování a využívání tříd a struktur (C++/CLI).
Operátor přiřazení vygenerovaný kompilátorem bude dodržovat obvyklá standardní pravidla jazyka C++ s následujícími dodatky:
Všechny nestatické datové členy, jejichž typ je popisovačem referenčního typu, se zkopírují (zachází se jako se statickým datovým členem, jehož typ je ukazatel).
Libovolný nestatický datový člen, jehož typem je typ hodnoty, se zkopíruje.
Jakýkoli nestatický datový člen, jehož typem je instance referenčního typu, vyvolá volání konstruktoru kopírování typu odkazu.
Kompilátor také poskytuje %
unární operátor pro převod instance referenčního typu vytvořeného pomocí sémantiky zásobníku na jeho základní typ popisovače.
Následující odkazové typy nejsou k dispozici pro použití sémantiky zásobníku:
Příklad
Popis
Následující ukázka kódu ukazuje, jak deklarovat instance referenčních typů s sémantikou zásobníku, jak funguje operátor přiřazení a konstruktor kopírování a jak inicializovat sledovací odkaz s odkazem vytvořeným pomocí sémantiky zásobníku.
Kód
// 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);
}
Výstup
98
98
98
13
13