参照型の C++ スタック セマンティクスC++ Stack Semantics for Reference Types

Visual Studio 2005 より前では、参照型のインスタンスは、 new ガベージコレクションヒープにオブジェクトを作成した演算子を使用してのみ作成できました。Prior to Visual Studio 2005, an instance of a reference type could only be created using the new operator, which created the object on the garbage collected heap. ただし、スタックでネイティブ型のインスタンスを作成する場合と同じ構文を使用して、参照型のインスタンスを作成できるようになりました。However, you can now create an instance of a reference type using the same syntax that you would use to create an instance of a native type on the stack. そのため、参照型のオブジェクトを作成するためにref new, gcnewを使用する必要はありません。So, you do not need to use ref new, gcnew to create an object of a reference type. また、オブジェクトがスコープ外に出ると、コンパイラはオブジェクトのデストラクターを呼び出します。And when the object goes out of scope, the compiler calls the object's destructor.

解説Remarks

スタックセマンティクスを使用して参照型のインスタンスを作成すると、コンパイラは、ガベージコレクションヒープにインスタンスを内部で作成します (を使用 gcnew )。When you create an instance of a reference type using stack semantics, the compiler does internally create the instance on the garbage collected heap (using gcnew).

関数のシグネチャまたは戻り値の型に値による参照型のインスタンスが含まれている場合、関数は、(modreq を使用した) 特別な処理を必要とするようにメタデータでマークされます。When the signature or return type of a function includes an instance of a by-value reference type, the function will be marked in the metadata as requiring special handling (with modreq). この特別な処理は、現在 Visual C++ クライアントによってのみ提供されています。他の言語では、現在、スタックセマンティクスで作成された参照型を使用する関数またはデータの使用はサポートされていません。This special handling is currently only provided by Visual C++ clients; other languages do not currently support consuming functions or data that use reference types created with stack semantics.

gcnew スタックセマンティクスの代わりに (動的割り当て) を使用する理由の1つは、型にデストラクターがない場合です。One reason to use gcnew (dynamic allocation) instead of stack semantics would be if the type has no destructor. また、関数を Visual C++ 以外の言語で使用する場合は、関数シグネチャでスタックセマンティクスで作成された参照型を使用することはできません。Also, using reference types created with stack semantics in function signatures would not be possible if you want your functions to be consumed by languages other than Visual C++.

コンパイラは、参照型のコピーコンストラクターを生成しません。The compiler will not generate a copy constructor for a reference type. そのため、シグネチャで値渡しの参照型を使用する関数を定義する場合は、参照型のコピーコンストラクターを定義する必要があります。Therefore, if you define a function that uses a by-value reference type in the signature, you must define a copy constructor for the reference type. 参照型のコピーコンストラクターには、という形式のシグネチャがあり R(R%){} ます。A copy constructor for a reference type has a signature of the following form: R(R%){}.

コンパイラは、参照型の既定の代入演算子を生成しません。The compiler will not generate a default assignment operator for a reference type. 代入演算子を使用すると、スタックセマンティクスを使用してオブジェクトを作成し、スタックセマンティクスを使用して作成された既存のオブジェクトを使用してオブジェクトを初期化できます。An assignment operator allows you to create an object using stack semantics and initialize it with an existing object created using stack semantics. 参照型の代入演算子には、という形式のシグネチャがあり void operator=( R% ){} ます。An assignment operator for a reference type has a signature of the following form: void operator=( R% ){}.

型のデストラクターが重要なリソースを解放し、参照型にスタックセマンティクスを使用する場合は、デストラクターを明示的に呼び出す必要はありません (またはを呼び出す必要はありません delete )。If your type's destructor releases critical resources and you use stack semantics for reference types, you do not need to explicitly call the destructor (or call delete). 参照型のデストラクターの詳細については、「方法: クラスと構造体を定義および使用する (C++/cli)」の「デストラクターとファイナライザー」を参照してください。For more information on destructors in reference types, see Destructors and finalizers in How to: Define and consume classes and structs (C++/CLI).

コンパイラによって生成された代入演算子は、次の追加機能を備えた通常の標準 C++ 規則に従います。A compiler-generated assignment operator will follow the usual standard C++ rules with the following additions:

  • 型が参照型へのハンドルである非静的データメンバーは、シャローコピーされます (型がポインターである非静的データメンバーのように扱われます)。Any non-static data members whose type is a handle to a reference type will be shallow copied (treated like a non-static data member whose type is a pointer).

  • 型が値型である非静的データメンバーは、シャローコピーされます。Any non-static data member whose type is a value type will be shallow copied.

  • 型が参照型のインスタンスである非静的データメンバーは、参照型のコピーコンストラクターへの呼び出しを呼び出します。Any non-static data member whose type is an instance of a reference type will invoke a call to the reference type’s copy constructor.

また、コンパイラは、 % スタックセマンティクスを使用して作成された参照型のインスタンスを基になるハンドル型に変換する単項演算子も提供します。The compiler also provides a % unary operator to convert an instance of a reference type created using stack semantics to its underlying handle type.

次の参照型は、スタックセマンティクスでは使用できません。The following reference types are not available for use with stack semantics:

Example

説明Description

次のコードサンプルは、スタックセマンティクスを使用して参照型のインスタンスを宣言する方法、代入演算子とコピーコンストラクターがどのように動作するか、およびスタックセマンティクスを使用して作成された参照型を使用して追跡参照を初期化する方法を示しています。The following code sample shows how to declare instances of reference types with stack semantics, how the assignment operator and copy constructor works, and how to initialize a tracking reference with reference type created using stack semantics.

コードCode

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

出力Output

98
98
98
13
13

関連項目See also

クラスと構造体Classes and Structs