オブジェクト演算子 (^) へのハンドル (C++ コンポーネント拡張)
ハンドルの declarators (「文字」とされる^)は、オブジェクトは、アクセス可能ではないことをシステムが判断するときに宣言されたオブジェクトが自動的に削除する必要があることを意味する型 指定子 を変更します。
宣言されたオブジェクトのアクセス
ハンドルの宣言で宣言された変数はオブジェクトへのポインターのように動作します。ただし、全体のオブジェクトへの変数が指すオブジェクトのメンバーには、ポイントできないため、ポインター演算をサポートしません。オブジェクトにオブジェクトのメンバーにアクセスするためにアクセスするには、間接演算子 ()と*矢印のメンバー アクセス演算子 (->)を使用します。
Windows ランタイム
コンパイラは、オブジェクトでは使用しない場合は、削除できるかどうかを確認するために COM 参照カウントの 機能を使用します。これは、 Windows ランタイム インターフェイスから派生したオブジェクトが実際に COM オブジェクトであるためです。参照カウントは、オブジェクトが null に設定されているまたはスコープの外に出ますデクリメントされますと、オブジェクトがインクリメントされますが、作成されるか、またはコピーする場合。参照カウントがゼロにメニュー、オブジェクトは自動的にとすぐに削除します。
ハンドルの宣言の長所は、明示的に面倒で、エラーが発生しやすいプロセスのオブジェクトの参照カウントを管理する必要がある COM、あります。つまり、参照カウントをインクリメントおよびデクリメントするオブジェクトの AddRef()と Release()メソッドをダイヤルします。ただし、ハンドルの宣言でオブジェクトを宣言する場合、 Visual C++ コンパイラは自動的に参照カウントを調整するコードを生成します。
オブジェクトをインスタンス化する方法の詳細については 新しい refを参照してください。
要件
コンパイラ オプション: /ZW
共通言語ランタイム
システムは、オブジェクトでは使用しない場合は、削除できるかどうかを確認するために、 CLR の ガベージ コレクターの 機能を使用します。共通言語ランタイムは、オブジェクトが割り当てられ、プログラムで使用するマネージ参照 (変数)は、ヒープ上のオブジェクトの場所を示しますヒープを保持します。オブジェクトが使用されなく場合は、ヒープで占めたメモリが解放されます。定期的に、ガベージ コレクターは、使用を実現するためのヒープを解放されたメモリを圧縮します。ヒープを圧縮すると、マネージ参照によって参照される場所が無効になるヒープのオブジェクトを移動できます。ただし、ガベージ コレクターは、すべてのマネージ参照の場所は、ヒープのオブジェクトの現在の位置を示すように自動的にそれらを更新します。
ネイティブ C++ のポインター (*)と参照&()が管理されていない参照ではないため、ガベージ コレクターによって自動的に、が指しているアドレスを更新できません。ガベージ コレクターがわかっていを自動的に更新できます。この問題を解決するには、変数を指定するには、ハンドルの宣言子を使用します。
Visual C++ 2002 と Visual C++ 2003 ではマネージ ヒープのオブジェクトを宣言するには、 __gc * が使用されました。^ は、新しい構文の __gc * を置き換えます。
詳細については、「方法: ネイティブ型のハンドルを宣言する」を参照してください。
例
例
このサンプルは、マネージ ヒープの参照型のインスタンスを作成する方法を示します。このサンプルは、マネージ同じオブジェクトへの 2 回の参照によってガベージコレクション ヒープ別の 1 種類のハンドルを初期化できることを示します。この 1 種類のハンドルへ 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();
}
出力
例
次の例では、オブジェクト型がボックス化された値型であるマネージ ヒープのオブジェクトへのハンドルを宣言する方法を示します。このサンプルでは、ボックス化されたオブジェクトから値型を取得する方法を示します。
// 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);
}
出力
例
このサンプルでは、任意のオブジェクトを指すように void* のポインターに使用する共通 C++ の用法は、参照クラスへのハンドルを保留できる Object^ に置換されることを示します。すべての配列とデリゲートなど、入力が、オブジェクトのハンドルに変換できます。示します。
// 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);
}
出力
例
このサンプルは、ハンドルが逆参照できること、およびメンバーが逆参照されるハンドルにアクセスできることを示します。
// 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
}
出力
例
このサンプルは int がガベージ コレクションが行われるヒープに格納されることがあります。とネイティブ参照は、マネージ ヒープのオブジェクトの移動を追跡したり、ネイティブ参照 (&)がマネージ型の int のメンバーにバインドできないことを示します。変更はローカル変数を使用するか、それに追跡参照を %するに & を変更することです。
// 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