Share via


Menangani ke Operator Objek (^) (C++/CLI dan C++/CX)

Deklarator handel (^, diucapkan "topi"), memodifikasi penentu jenis untuk berarti bahwa objek yang dideklarasikan harus dihapus secara otomatis ketika sistem menentukan bahwa objek tidak lagi dapat diakses.

Mengakses Objek Yang Dideklarasikan

Variabel yang dideklarasikan dengan deklarator gagang bersifat seperti penunjuk ke objek. Namun, variabel menunjuk ke seluruh objek, tidak dapat menunjuk ke anggota objek, dan tidak mendukung aritmatika pointer. Gunakan operator tidak langsung (*) untuk mengakses objek, dan operator akses anggota panah (->) untuk mengakses anggota objek.

Windows Runtime

Pengkompilasi menggunakan mekanisme penghitungan referensi COM untuk menentukan apakah objek tidak lagi digunakan dan dapat dihapus. Ini dimungkinkan karena objek yang berasal dari antarmuka Windows Runtime sebenarnya adalah objek COM. Jumlah referensi bertambah saat objek dibuat atau disalin, dan diderementasikan saat objek diatur ke null atau keluar dari cakupan. Jika jumlah referensi masuk ke nol, objek secara otomatis dan segera dihapus.

Keuntungan dari deklarator handel adalah bahwa dalam COM Anda harus secara eksplisit mengelola jumlah referensi untuk objek, yang merupakan proses yang melelahkan dan rawan kesalahan. Artinya, untuk menambah dan mengurangi jumlah referensi, Anda harus memanggil metode AddRef() dan Release() objek. Namun, jika Anda mendeklarasikan objek dengan deklarator handel, pengkompilasi menghasilkan kode yang secara otomatis menyesuaikan jumlah referensi.

Untuk informasi tentang cara membuat instans objek, lihat meref baru.

Persyaratan

Opsi pengkompilasi: /ZW

Runtime Bahasa Umum

Sistem ini menggunakan mekanisme pengumpul sampah CLR untuk menentukan apakah objek tidak lagi digunakan dan dapat dihapus. Runtime bahasa umum mempertahankan timbunan tempat ia mengalokasikan objek, dan menggunakan referensi terkelola (variabel) dalam program Anda menunjukkan lokasi objek pada tumpukan. Ketika objek tidak lagi digunakan, memori yang ditempatinya pada tumpukan dibesarkan. Secara berkala, pengumpul sampah memampatkan tumpukan untuk lebih baik menggunakan memori yang dibebaskan. Memampatkan tumpukan dapat memindahkan objek pada timbunan, yang membatalkan lokasi yang dimaksud oleh referensi terkelola. Namun, pengumpul sampah mengetahui lokasi semua referensi terkelola, dan secara otomatis memperbaruinya untuk menunjukkan lokasi objek saat ini pada tumpukan.

Karena penunjuk C++ asli (*) dan referensi (&) bukan referensi terkelola, pengumpul sampah tidak dapat secara otomatis memperbarui alamat yang mereka arahkan. Untuk mengatasi masalah ini, gunakan deklarator handel untuk menentukan variabel yang diketahui pengumpul sampah dan dapat memperbarui secara otomatis.

Untuk informasi selengkapnya, lihat Cara: Mendeklarasikan Handel dalam Jenis Asli.

Contoh

Sampel ini menunjukkan cara membuat instans jenis referensi pada tumpukan terkelola. Sampel ini juga menunjukkan bahwa Anda dapat menginisialisasi satu handel dengan handel lain, menghasilkan dua referensi ke objek yang sama pada tumpukan terkelola yang dikumpulkan sampah. Perhatikan bahwa menetapkan nullptr ke satu handel tidak menandai objek untuk pengumpulan sampah.

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

Sampel berikut menunjukkan cara mendeklarasikan handel ke objek pada tumpukan terkelola, di mana jenis objek adalah jenis nilai kotak. Sampel juga menunjukkan cara mendapatkan jenis nilai dari objek berkotak.

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

Sampel ini menunjukkan bahwa idiom C++ umum menggunakan void* pointer untuk menunjuk ke objek arbitrer digantikan oleh Object^, yang dapat menahan handel ke kelas referensi apa pun. Ini juga menunjukkan bahwa semua jenis, seperti array dan delegasi, dapat dikonversi ke handel objek.

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

Sampel ini menunjukkan bahwa handel dapat didereferensikan dan anggota dapat diakses melalui handel dereferensi.

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

Sampel ini menunjukkan bahwa referensi asli (&) tidak dapat mengikat int anggota jenis terkelola, karena int mungkin disimpan dalam tumpukan yang dikumpulkan sampah, dan referensi asli tidak melacak pergerakan objek di tumpukan terkelola. Perbaikannya adalah menggunakan variabel lokal, atau untuk mengubah & ke %, menjadikannya referensi pelacakan.

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

Persyaratan

Opsi pengkompilasi: /clr

Baca juga

Ekstensi Komponen untuk .NET dan UWP
Operator Referensi Pelacakan