Semantyka stosu języka C++ dla typów odwołań

Przed Visual Studio 2005 new r. wystąpienie typu odwołania można było utworzyć tylko przy użyciu operatora , który utworzył obiekt na stercie odśmiecania pamięci. Można jednak teraz utworzyć wystąpienie typu referencyjnego przy użyciu tej samej składni, która jest następnie używany do tworzenia wystąpienia typu natywnego na stosie. Dlatego nie trzeba używać ref new, gcnew do tworzenia obiektu typu odwołania. Gdy obiekt wykracza poza zakres, kompilator wywołuje destruktor obiektu.

Uwagi

Podczas tworzenia wystąpienia typu referencyjnego przy użyciu semantyki stosu kompilator wewnętrznie tworzy wystąpienie na stercie zebranej odśmiecania pamięci (przy użyciu klasy gcnew).

Gdy podpis lub zwracany typ funkcji zawiera wystąpienie typu referencyjnego według wartości, funkcja zostanie oznaczona w metadanych jako wymagająca specjalnej obsługi (z modreq). Ta specjalna obsługa jest obecnie zapewniana tylko przez Visual C++ klientów; Inne języki nie obsługują obecnie funkcji ani danych, które używają typów referencyjnych utworzonych za pomocą semantyki stosu.

Jednym z powodów użycia gcnew (alokacja dynamiczna) zamiast semantyki stosu jest brak destruktora typu. Ponadto używanie typów referencyjnych utworzonych za pomocą semantyki stosu w podpisach funkcji nie byłoby możliwe, jeśli funkcje mają być używane przez języki inne niż Visual C++.

Kompilator nie wygeneruje konstruktora kopiowania dla typu odwołania. W związku z tym w przypadku definiowania funkcji, która używa typu odwołania według wartości w sygnaturze, należy zdefiniować konstruktor kopiatora dla typu referencyjnego. Konstruktor kopiując dla typu referencyjnego ma podpis o następującej postaci: R(R%){}.

Kompilator nie wygeneruje domyślnego operatora przypisania dla typu odwołania. Operator przypisania umożliwia utworzenie obiektu przy użyciu semantyki stosu i zainicjowanie go z istniejącym obiektem utworzonym przy użyciu semantyki stosu. Operator przypisania dla typu odwołania ma podpis o następującej postaci: void operator=( R% ){}.

Jeśli destruktor typu zwalnia krytyczne zasoby i używa semantyki stosu dla typów referencyjnych, nie trzeba jawnie wywołać destruktora (lub wywołać ).delete Aby uzyskać więcej informacji na temat destruktorów w typach referencyjnych, zobacz Destruktory i finalizatory w te tematach How to: Define and consume classes and structs (C++/CLI).

Operator przypisania wygenerowany przez kompilator będzie przestrzegać zwykłych standardowych reguł języka C++ z następującymi dodatkami:

  • Wszystkie niestatyczne składowe danych, których typ jest dojściem do typu referencyjnego, zostaną pobieskie skopiowane (będą traktowane jak niestatycznych składowych danych, których typ jest wskaźnikiem).

  • Wszelkie niestatyczne elementy członkowskie danych, których typ jest typem wartości, zostaną skopiowane pobiebienie.

  • Każdy element członkowski danych niestatycznych, którego typ jest wystąpieniem typu referencyjnego, wywoła wywołanie konstruktora kopiowania typu odwołania.

Kompilator udostępnia również operator jednoargowy % do konwertowania wystąpienia typu referencyjnego utworzonego przy użyciu semantyki stosu na jego podstawowy typ dojścia.

Następujące typy referencyjne nie są dostępne do użycia z semantyką stosu:

Przykład

Opis

Poniższy przykład kodu przedstawia sposób deklarowania wystąpień typów referencyjnych za pomocą semantyki stosu, sposobu działania operatora przypisania i konstruktora kopiowania oraz inicjowania odwołania do śledzenia z typem referencyjnym utworzonym przy użyciu semantyki stosu.

Kod

// 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);
}

Dane wyjściowe

98
98
98
13
13

Zobacz też

Klasy i struktury