Sdílet prostřednictvím


Operátor popisovače objektu (^) (rozšíření komponent C++)

Deklarátor popisovače (^, výslovnost "stříška") změní typ specifikátor, aby znamenal, že deklarovaný objekt má být automaticky odstraněn, když systém zjistí, že objekt již není přístupný.

Přístup k deklarovanému objektu

Proměnná, která je deklarována pomocí deklarátoru popisovače, se chová jako ukazatel na objekt.Proměnná však odkazuje na celý objekt a nemůže odkazovat na člena objektu a nepodporuje aritmetiku ukazatele.Použijte operátor dereference (*) pro přístup k objektu a šipku operátora přístupu členů (->) pro přístup ke členu objektu.

prostředí Windows Runtime

Kompilátor používá mechanismus počítání odkazů COM k určení, zda objekt již není používán a může být odstraněn.To je možné, protože objekt, který je odvozen z rozhraní Windows Runtime je ve skutečnosti objekt modelu COM.Počet odkazů je zvýšen, když je objekt vytvořen nebo zkopírován a snížen, když je objekt nastaven na hodnotu null nebo přejde mimo obor.V případě, že počet odkazů dosáhne nuly, objekt je automaticky a okamžitě odstraněn.

Výhodou deklarátoru popisovač je, že v COM musíte explicitně spravovat počet odkazů pro objekt, což je únavné a snadno dojde k chybám.To znamená zvýšit a snížit počet odkazů, které musíte volat pro metody AddRef() a Release() objektu.Nicméně pokud deklarujete objekt s deklarátorem popisovače, kompilátor Visual C++ vygeneruje kód, který automaticky přizpůsobí počet odkazů.

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

Požadavky

Možnost kompilátoru: /ZW

Common Language Runtime

Systém používá mechanismus uvolňování paměti CLR k určení, zda objekt již není používán a může být odstraněn.Common Language Runtime udržuje haldu, na které se přidělují objekty a používá spravované odkazy (proměnné) v programu pro označení umístění objektů na haldě.Když objekt již není používán, uvolní se paměť, která je obsazena na haldě.Uvolňování paměti pravidelně zkomprimuje hladu k lepšímu využití uvolněné paměti.Komprimací haldy můžete přesunout objekty do haldy, čímž bude zrušena platnost umístění uváděná spravovanými odkazy.Nicméně uvolňování paměti zná umístění všech spravovaných odkazů a automaticky je aktualizuje pro označení aktuálního umístění objektů na haldě.

Protože nativní ukazatelé C++ (*) a odkazy (&) nejsou spravované odkazy, kolektor uvolňování nemůže automaticky aktualizovat adresy, na které odkazují.Chcete-li tento problém vyřešit, použijte deklarátor popisovače k určení proměnné, kterou si uvědomuje uvolňování paměti a lze ji automaticky aktualizovat.

Ve verzích Visual C++ 2002 a Visual C++ 2003 bylo __gc * používáno k deklarování objektu na spravované haldě. ^ v nové syntaxi nahrazuje __gc *.

Další informace naleznete v tématu Postupy: Deklarace obslužných rutin v nativních typech.

Příklady

Příklad

Tento příklad ukazuje, jak vytvořit instanci typu odkazu na spravované haldě. Tento příklad také ukazuje, že inicializace jednoho popisovače jiným vytvoří dva odkazy na stejný objekt na spravované haldě uvolňování paměti.Všimněte si, že přiřazení nullptr (rozšíření komponent C++) k popisovači neoznačí 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();   
}

Výsledek

12

Příklad

Následující příklad ukazuje, jak deklarovat popisovač pro objekt na spravované haldě, kde typem objektu je zabalený typ hodnoty.Vzorek ukazuje, jak získat typ hodnoty ze zabalené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);
}

Výsledek

  
  

Příklad

Tento příklad ukazuje, že běžný idiom C++ používání ukazatele void* ukazující na libovolný objekt je nahrazen pomocí Object^, který může obsahovat popisovač na referenční třídu.Také ukazuje, že všechny typy, jako jsou pole a delegáty, mohou být převedeny 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);
}

Výsledek

  
  
  

Příklad

Tento příklad ukazuje, že popisovač může být dereferencován a že lze získat přístup k členovi pomocí dereferencovaného popisovače.

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

Výsledek

  
  

Příklad

Tento příklad ukazuje, že nativní odkaz (&) nemůže vytvořit vazbu se členem int spravovaného typu, protože int lze uložit ve spravované haldě uvolňování paměti a nativní odkazy nesledují pohyb objektu ve spravované haldě.Opravou je použití místní proměnné nebo změna & na %, čímž vytvoříte sledovací odkaz.

// 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é

Referenční dokumentace

Operátor sledovacího odkazu (rozšíření komponent C++)

Koncepty

Rozšíření komponent pro platformy běhového prostředí