物件控制代碼運算子 (^) (C++ 元件擴充功能)
處理宣告子 (^,讀成"hat"),會修改型別規範 ,意指宣告的物件應該自動刪除當系統決定的物件不再是可存取。
存取已宣告的物件
使用控制代碼宣告子宣告的變數的行為類似物件的指標。不過,整個的物件變數指向不可指向物件的成員,而且它不支援指標算術。使用間接取值運算子 (*) 來存取該物件和箭號的成員存取運算子 (->) 來存取物件的成員。
Windows 執行階段
編譯器會使用 COM 參考計數機制,可決定是否物件已不再使用,且可刪除。這可能是因為物件是衍生自 Windows 執行階段介面是一個 COM 物件。參考計數會漸增,該物件時建立或複製,並減少當物件設定為 null 或而言超出範圍。如果參考次數歸零,物件會自動且立即刪除。
控制代碼宣告子的優點是在 COM,您必須明確地管理此物件會是冗長乏味而的錯誤很容易出錯的程序的參考次數。也就是遞增及遞減的參考次數,您必須呼叫物件的 AddRef() 和 Release() 的方法。不過,如果您宣告物件的控制代碼宣告子時,Visual C++ 編譯器會產生程式碼會自動調整之參考次數。
如需詳細資訊來具現化物件,請參閱 ref 新。
需求
編譯器選項:/ZW
Common Language Runtime
系統會使用 CLR 記憶體回收行程機制,可決定是否物件已不再使用,且可刪除。Common language runtime 維護的堆積,它會配置物件,並使用 managed 的參考 (變數),在您的程式中表示物件在堆積上的位置。當物件不再使用時,會釋放它所佔用堆積的記憶體。請定期記憶體回收行程壓縮堆積更適當的使用已釋放的記憶體。壓縮堆積,可以在 「 堆集,會使位置來參考到無效的受管理的參照來移動物件。然而,記憶體回收行程所知之位置的受管理的所有參考,而且會自動更新這些指示的物件在堆積上的目前位置。
因為原生 C++ 指標 (*) 和參考 (&) 並不受管理的參考,記憶體回收行程無法自動更新其指向的位址。若要解決這個問題,讓您指定的變數,記憶體回收行程所知的控制代碼宣告子,可自動更新。
在 Visual C++ 2002年與 Visual C++ 2003, __gc *用來宣告 managed 堆積上的物件。^會取代__gc *在新語法中。
如需詳細資訊,請參閱 HOW TO:以原生型別宣告控制代碼。
範例
範例
這個範例會示範如何建立 managed 堆積上的參考型別的執行個體。這個範例也會顯示您可以初始化一個控制碼與另一個,導致在受管理、 記憶體回收堆積上的同一個物件的兩個參考。請注意,指定nullptr (C++ 元件擴充功能)不到一個控制碼會標記為記憶體回收的物件。
// 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
範例
下列範例會示範如何在 managed 堆積,其中的物件類型是 boxed 實的值型別中宣告的物件控制代碼。此範例也顯示如何從 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
範例
這個範例會示範 C++ 的通用慣用語使用 void 1 指標移向 [任意物件已由物件 ^,它可保留控制代碼的任何參考類別。它也會顯示所有的型別,例如陣列和委派,可轉為物件控制代碼。
// 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
範例
這個範例會示範一個控點可以被解除參考且成員可以存取透過解除參考的控點。
// 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
範例
這個範例會示範,原生參考 (&) 無法繫結至int的 managed 型別,成員做為int項目會儲存在記憶體回收堆積,和原生參考不會追蹤在 managed 堆積中的物件移動。若要使用的區域變數,或變更,則修正&到%,使其成為追蹤參考。
// 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
}
需求
編譯器選項:/clr