参照型の C++ スタック セマンティクス
Visual C++ 2005 以前で参照型のインスタンスがガベージ コレクションによって収集されたヒープにオブジェクトを作成した new の演算子を使用して作成できません。ただし、スタックのネイティブ型のインスタンスを作成するためにある同じ構文を使用して、参照型のインスタンスを作成できます。このため、参照型のオブジェクトを作成するには、ref new、gcnew (C++ コンポーネント拡張) を使用する必要はありません。およびオブジェクトがスコープ外に出ると、コンパイラがオブジェクトのデストラクターを呼び出します。
解説
スタックのセマンティクスを使用して参照型のインスタンスを作成すると、コンパイラは内部的にガベージ コレクションが行われるヒープのインスタンスを作成します (gcnewを使用)。
関数の定義または戻り値の型が値渡しの参照型のインスタンスが含まれる場合、関数はマークされている場合、特別な処理が必要です modreq ようにメタデータ (と)。この特別な処理は、現在 Visual C++ クライアントによっては使用できません; 他の言語では、現在のスタック セマンティクスと作成される参照型を使用する関数またはデータを実行することはできません。
スタックのセマンティクスの代わりに gcnew (動的割り当て) を使用する 1 とおりのは、型にデストラクターが必要です。また、関数に Visual C++ 以外の言語によって実行されるようにするには、関数定義のスタックの意味で作成された参照型を使用することではありません。
コンパイラは参照型のコピー コンストラクターを生成しません。したがって、定義に対して参照型を使用する関数を定義する場合は、参照型のコピー コンストラクターを定義する必要があります。参照型のコピー コンストラクターに次の形式の定義があります: R(R%){}。
コンパイラは参照型の既定の代入演算子は生成されません。代入演算子は、オブジェクトをスタックのセマンティクスを使用して作成し、スタックのセマンティクスを使用して作成した既存のオブジェクトで初期化できます。参照型の代入演算子は次の形式の定義を含んでいます: void operator=( R% ){}。
カスタム型のデストラクターが必要なリソースを参照型のセマンティクス解放スタック使用する場合は、明示的にデストラクターを呼び出す必要はありません (または deleteを呼び出すため)。参照型のデストラクターの詳細については、Visual C++ のデストラクターおよびファイナライザーを参照してください。
コンパイラが生成した代入演算子は次の追加と通常の C++ 標準規則に従っています:
型が参照型のハンドルです。コピーする非静的データ メンバーが簡易です (型がポインターである) の非静的データ メンバーとして処理する。
型が値型でコピーする非静的データ メンバーが簡易です。
型が参照型のインスタンスであるすべての非静的データ メンバーが参照型のコピー コンストラクターへの呼び出しを開始します。
コンパイラは、基になるハンドル型にスタックのセマンティクスを使用して作成される参照型のインスタンスを変換するには % の単項演算子が用意されています。
次の参照型のセマンティクスはスタックでは使用できません:
例
説明
次のコード例では、代入演算子とコピー コンストラクターの動作、およびスタックのセマンティクスを使用して作成される参照型で追跡参照を初期化する方法を示します。スタックのセマンティクスの参照型のインスタンスを宣言する方法を示します。
コード
// stack_semantics_for_reference_types.cpp
// compile with: /clr
ref class R {
public:
int i;
R(){}
// assignment operator
void operator=(R% r) {
i = r.i;
}
// copy constructor
R(R% r) : i(r.i) {}
};
void Test(R r) {} // requires copy constructor
int main() {
R r1;
r1.i = 98;
R r2(r1); // requires copy constructor
System::Console::WriteLine(r1.i);
System::Console::WriteLine(r2.i);
// use % unary operator to convert instance using stack semantics
// to its underlying handle
R ^ r3 = %r1;
System::Console::WriteLine(r3->i);
Test(r1);
R r4;
R r5;
r5.i = 13;
r4 = r5; // requires a user-defined assignment operator
System::Console::WriteLine(r4.i);
// initialize tracking reference
R % r6 = r4;
System::Console::WriteLine(r6.i);
}
出力
98
98
98
13
13