Operátor popisovače objektu (^) (C++/CLI a C++/CX)

Deklarátor popisovače (^vyslovovaný "hat"), upraví specifikátor typu tak, aby měl být deklarovaný objekt automaticky odstraněn, když systém zjistí, že objekt již není přístupný.

Přístup k deklarovanému objektu

Proměnná deklarovaná pomocí deklarátoru popisovače se chová jako ukazatel na objekt. Proměnná však odkazuje na celý objekt, nemůže odkazovat na člena objektu a nepodporuje aritmetické ukazatele. Pro přístup k objektu použijte operátor nepřímého přístupu (*) a operátor pro přístup člena šipky (->) pro přístup k členu objektu.

prostředí Windows Runtime

Kompilátor používá mechanismus počítání odkazů modelu COM k určení, zda objekt již není používán a lze jej odstranit. To je možné, protože objekt odvozený z rozhraní prostředí Windows Runtime je ve skutečnosti objekt COM. Počet odkazů se zvýší při vytvoření nebo zkopírování objektu a dekrementuje se, když je objekt nastaven na hodnotu null nebo přestane být obor. Pokud počet odkazů přejde na nulu, objekt se automaticky a okamžitě odstraní.

Výhodou deklarátoru popisovače je, že v modelu COM musíte explicitně spravovat počet odkazů pro objekt, což je zdlouhavý a náchylný proces chyby. To znamená, že chcete-li zvýšit a zvýšit počet odkazů, musíte volat metody AddRef() a Release() objektu. Pokud však deklarujete objekt s deklarátorem popisovače, kompilátor vygeneruje kód, který automaticky upraví počet odkazů.

Informace o tom, jak vytvořit instanci objektu, naleznete v tématu odkaz nové.

Požadavky

Možnost kompilátoru: /ZW

CLR (Common Language Runtime)

Systém používá mechanismus uvolňování paměti CLR k určení, jestli se objekt už nepoužívá a lze jej odstranit. Modul CLR (Common Language Runtime) udržuje haldu, na které přiděluje objekty, a používá spravované odkazy (proměnné) ve vašem programu označující umístění objektů v haldě. Pokud se objekt už nepoužívá, uvolní se paměť, kterou zabírá na haldě. Uvolňování paměti pravidelně komprimuje haldu, aby lépe používala uvolněnou paměť. Komprimace haldy může přesunout objekty v haldě, která zneplatní umístění odkazované spravovanými odkazy. Systém uvolňování paměti však ví o umístění všech spravovaných odkazů a automaticky je aktualizuje tak, aby označoval aktuální umístění objektů v haldě.

Vzhledem k tomu, že nativní ukazatele jazyka C++ a odkazy (*&) nejsou spravované odkazy, systém uvolňování paměti nemůže automaticky aktualizovat adresy, na které odkazují. Chcete-li tento problém vyřešit, pomocí deklarátoru popisovače určete proměnnou, o které je systém uvolňování paměti informován a může se automaticky aktualizovat.

Další informace naleznete v tématu Postupy: Deklarace popisovačů v nativních typech.

Příklady

Tato ukázka ukazuje, jak vytvořit instanci referenčního typu ve spravované haldě. Tato ukázka také ukazuje, že můžete inicializovat jeden popisovač s druhým, což vede ke dvěma odkazům na stejný objekt při spravované haldě shromážděné paměti. Všimněte si, že přiřazení nullptr k jednomu popisovači neoznačuje objekt pro uvolňování paměti.

// mcppv2_handle.cpp
// compile with: /clr
ref class MyClass {
public:
   MyClass() : i(){}
   int i;
   void Test() {
      i++;
      System::Console::WriteLine(i);
   }
};

int main() {
   MyClass ^ p_MyClass = gcnew MyClass;
   p_MyClass->Test();

   MyClass ^ p_MyClass2;
   p_MyClass2 = p_MyClass;

   p_MyClass = nullptr;
   p_MyClass2->Test();
}
1
2

Následující ukázka ukazuje, jak deklarovat popisovač objektu ve spravované haldě, kde typ objektu je typ hodnoty v rámečku. Ukázka také ukazuje, jak získat typ hodnoty z boxovaného objektu.

// mcppv2_handle_2.cpp
// compile with: /clr
using namespace System;

void Test(Object^ o) {
   Int32^ i = dynamic_cast<Int32^>(o);

   if(i)
      Console::WriteLine(i);
   else
      Console::WriteLine("Not a boxed int");
}

int main() {
   String^ str = "test";
   Test(str);

   int n = 100;
   Test(n);
}
Not a boxed int
100

Tato ukázka ukazuje, že společný idiom jazyka C++ použití void* ukazatele na odkaz na libovolný objekt je nahrazen , Object^který může obsahovat popisovač jakékoli referenční třídy. Ukazuje také, že všechny typy, jako jsou pole a delegáti, lze převést na popisovač objektu.

// mcppv2_handle_3.cpp
// compile with: /clr
using namespace System;
using namespace System::Collections;
public delegate void MyDel();
ref class MyClass {
public:
   void Test() {}
};

void Test(Object ^ x) {
   Console::WriteLine("Type is {0}", x->GetType());
}

int main() {
   // handle to Object can hold any ref type
   Object ^ h_MyClass = gcnew MyClass;

   ArrayList ^ arr = gcnew ArrayList();
   arr->Add(gcnew MyClass);

   h_MyClass = dynamic_cast<MyClass ^>(arr[0]);
   Test(arr);

   Int32 ^ bi = 1;
   Test(bi);

   MyClass ^ h_MyClass2 = gcnew MyClass;

   MyDel^ DelInst = gcnew MyDel(h_MyClass2, &MyClass::Test);
   Test(DelInst);
}
Type is System.Collections.ArrayList

Type is System.Int32

Type is MyDel

Tato ukázka ukazuje, že popisovač může být dereferenced a že člen může být přístupný prostřednictvím popisovače dereferenced.

// mcppv2_handle_4.cpp
// compile with: /clr
using namespace System;
value struct DataCollection {
private:
   int Size;
   array<String^>^ x;

public:
   DataCollection(int i) : Size(i) {
      x = gcnew array<String^>(Size);
      for (int i = 0 ; i < Size ; i++)
         x[i] = i.ToString();
   }

   void f(int Item) {
      if (Item >= Size)
      {
         System::Console::WriteLine("Cannot access array element {0}, size is {1}", Item, Size);
         return;
      }
      else
         System::Console::WriteLine("Array value: {0}", x[Item]);
   }
};

void f(DataCollection y, int Item) {
   y.f(Item);
}

int main() {
   DataCollection ^ a = gcnew DataCollection(10);
   f(*a, 7);   // dereference a handle, return handle's object
   (*a).f(11);   // access member via dereferenced handle
}
Array value: 7

Cannot access array element 11, size is 10

Tato ukázka ukazuje, že nativní odkaz (&) nemůže svázat s int členem spravovaného typu, protože int může být uložen v haldě s uvolňováním paměti a nativní odkazy nesledují přesun objektů ve spravované haldě. Opravou je použití místní proměnné nebo změna & , aby se odkaz na %sledování použil.

// mcppv2_handle_5.cpp
// compile with: /clr
ref struct A {
   void Test(unsigned int &){}
   void Test2(unsigned int %){}
   unsigned int i;
};

int main() {
   A a;
   a.i = 9;
   a.Test(a.i);   // C2664
   a.Test2(a.i);   // OK

   unsigned int j = 0;
   a.Test(j);   // OK
}

Požadavky

Možnost kompilátoru: /clr

Viz také

Přípony komponent pro .NET a UPW
Operátor sledovacího odkazu