Condividi tramite


Operatore handle a oggetto (^) (Estensioni del componente C++)

Il dichiaratore di handle (^, “circonflesso„ compilazione), modificare il tipo identificatore per indicare che l'oggetto dichiarato deve essere eliminato automaticamente quando il sistema stabilisce che l'oggetto non è più accessibile.

Accedere all'oggetto dichiarato

Una variabile dichiarata con il dichiaratore di handle si comporta come un puntatore all'oggetto.Tuttavia, la variabile punti all'intero oggetto, non possono indicare un membro dell'oggetto e non supporta l'aritmetica dei puntatori.L'operatore di riferimento indiretto (*) per accedere all'oggetto e l'operatore di accesso ai membri della freccia (->) per accedere a un membro dell'oggetto.

Windows Runtime

Il compilatore utilizza il meccanismo di conteggio dei riferimenti COM per determinare se esiste più in uso e non può essere eliminato.Ciò è possibile poiché un oggetto derivato da un'interfaccia runtime di windows è in realtà un oggetto COM.Il conteggio dei riferimenti viene incrementato quando viene creato l'oggetto o copiato e diminuisce quando l'oggetto è impostato per annullare o esce dall'ambito.Se il conteggio dei riferimenti andare a zero, l'oggetto automaticamente e viene eliminato immediatamente.

Il vantaggio del dichiaratore di handle è quello in COM che è necessario gestire in modo esplicito il conteggio dei riferimenti per un oggetto, che è un processo noiosa e il rischio all'errore.Ovvero per incrementare o decrementare il conteggio dei riferimenti è necessario chiamare il AddRef oggetto () e rilasciare () i metodi.Tuttavia, se si dichiara un oggetto con il dichiaratore di handle, il compilatore di Visual C++ genera codice che regola automaticamente il conteggio dei riferimenti.

Per informazioni su come creare un'istanza di un oggetto, vedere riferimento nuovo.

Requisiti

Opzione del compilatore: /ZW

Common Language Runtime

Il sistema utilizza il meccanismo di Garbage Collector di common language runtime per determinare se esiste più in uso e non può essere eliminato.Common Language Runtime gestisce un heap in cui alloca gli oggetti e utilizza i riferimenti gestiti (variabili) nel programma indica la posizione degli oggetti nell'heap.Quando un oggetto non è più utilizzato, la memoria che occupato nell'heap viene liberata.Periodicamente, il Garbage Collector comprime l'heap per migliorare l'utilizzo della memoria liberata.Comprimere l'heap può spostare gli oggetti nell'heap, che invalida le posizioni indicate dai riferimenti gestiti.Tuttavia, il Garbage Collector è presente la posizione di tutti i riferimenti gestiti e li aggiorna automaticamente per indicare la posizione corrente di oggetti nell'heap.

Poiché i puntatori nativi C++ (*) e i riferimenti (&) non sono riferimenti gestiti, il Garbage Collector non può aggiornare automaticamente gli indirizzi che indicano.Per risolvere questo problema, utilizzare il dichiaratore handle per specificare una variabile che il Garbage Collector sia consapevole di e può aggiornare automaticamente.

In Visual C++ 2002 e Visual C++ 2003, __gc * è stato utilizzato per dichiarare un oggetto nell'heap gestito.^ sostituisce __gc * nella nuova sintassi.

Per ulteriori informazioni, vedere Procedura: dichiarare handle in tipi nativi.

yk97tc08.collapse_all(it-it,VS.110).gifEsempi

Esempio

In questo esempio viene illustrato come creare un'istanza di un tipo di riferimento nell'heap gestito.In questo esempio viene inoltre mostrato che è possibile inizializzare un handle a un altro, con conseguente due riferimenti allo stesso oggetto dell'heap gestito e sottoposto a garbage collection.Si noti che assegna nullptr (Estensioni del componente C++) a un handle non contrassegna l'oggetto per Garbage Collection.

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

Output

  
  

Esempio

Di seguito viene illustrato come dichiarare un handle a un oggetto nell'heap gestito, in cui il tipo di oggetto è un tipo di valore boxed.Nell'esempio viene inoltre mostrato come ottenere il tipo di valore dall'oggetto boxed.

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

Output

  
  

Esempio

In questo esempio viene mostrato che l'idioma comune di C++ tramite un puntatore di void* in modo che punti a un oggetto arbitrario viene sostituito da Object^, che può contenere un handle per una classe di riferimento.Viene inoltre mostrato che tutti i tipi, quali matrici e delegati, possono essere convertiti in un oggetto.

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

Output

  
  
  

Esempio

In questo esempio viene mostrato che l'handle può essere derefenziate e che un membro è accessibile tramite handle derefenziate.

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

Output

  
  

Esempio

In questo esempio viene mostrato che un riferimento nativo (&) non può essere associato a un membro di int di un tipo gestito, ad esempio int potrebbe essere archiviato nell'heap sottoposto a garbage collection e i riferimenti nativi non tiene traccia del movimento di un oggetto nell'heap gestito.La correzione è utilizzare una variabile locale, o modificare & a %, rendendola un riferimento di rilevamento.

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

yk97tc08.collapse_all(it-it,VS.110).gifRequisiti

Opzione del compilatore: /clr

Vedere anche

Riferimenti

Operatore di riferimento di rilevamento (Estensioni del componente C++)

Concetti

Estensioni componenti per le piattaforme runtime