Sdílet prostřednictvím


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

Viz také

Třídy a struktury