特定のコンピュータプログラミング言語では、データ型は値型と参照型に分類されます。参照型は常に参照を介して暗黙的にアクセスされますが、値型の変数には値自体が直接含まれます。[1] [2]
値型と参照型のプロパティ
このような区別がある言語であっても、値型と参照型の正確な特性は言語によって異なりますが、一般的な特性は次のとおりです。
- ブール値、固定サイズの整数、浮動小数点値、文字などのプリミティブ データ型は値型です。
- オブジェクト指向プログラミングの意味でのオブジェクトは、参照型に属します。
- 参照型の変数に割り当てると、参照がコピーされるだけですが、値型の変数に割り当てると、値がコピーされます。これは、ローカル変数、オブジェクトのフィールド、配列要素など、すべての種類の変数に適用されます。関数を呼び出す場合も同様です。参照型のパラメーターは参照のコピーですが、値型のパラメーターは値のコピーです。
- 参照型が変更可能な場合、1 つの参照を介して行われた変更は他の参照を介して表示されますが、値型が変更可能な場合は、1 つの値に対して行われた変更は別の値では表示されません。
- 参照型は同一性の概念をサポートします。つまり、参照型の 2 つの値が同じオブジェクトを参照しているかどうかを議論することは理にかなっており、言語はそれらが同じオブジェクトを参照しているかどうかを判断する機能を提供しますが、値型はそうではありません。
- 参照型の値はヒープに割り当てられたオブジェクトを参照しますが、値型の値は呼び出しスタック (ローカル変数および関数パラメータの場合) またはそれを含むエンティティ (オブジェクトのフィールドおよび配列要素の場合) 内に含まれます。 (参照型の場合、呼び出しスタックまたはそれを含むエンティティ内に含まれるのは参照自体のみです。)
- 参照型はサブタイプの概念をサポートします。これにより、特定の参照型のすべての値が自動的に別の参照型の値になります。値型はサブタイプをサポートしませんが、必要に応じて整数を浮動小数点数に自動的に変換するなど、他の形式の暗黙的な型変換
intをサポートする場合があります。さらに、特定の値型と参照型の間で暗黙的な変換が行われる場合があります。たとえば、プリミティブ(値型) をIntegerオブジェクト (オブジェクト型) に「ボックス化」したり、「アンボックス化」によってこれを逆にしたりします。
参照型と「共有による呼び出し」
関数の引数が「値渡し」セマンティクスを使用して渡される場合でも (Java では常にそうであり、C# ではデフォルトでそうである)、参照型の値は本質的に参照です。そのため、パラメーターが参照型に属する場合、結果の動作は「参照渡し」セマンティクスに似ています。この動作は、共有による呼び出しと呼ばれることもあります。
共有による呼び出しは、関数が引数として受け取ったオブジェクトを変更する場合、参照による呼び出しに似ています。その場合、呼び出し元と関数は同じオブジェクトへの参照を持つため、呼び出し元にも変更が表示されます。関数がパラメータを別の参照に割り当てる場合、共有による呼び出しは参照による呼び出しとは異なります。その場合、両方の参照が最初は同じオブジェクトを指していても、呼び出し元と関数には別々の参照があるため、 この割り当ては呼び出し元には表示されません。
参照型と明示的なポインタ
多くの言語には明示的なポインタまたは参照があります。参照型は、参照先のエンティティには常に参照を介してアクセスされるという点でこれらとは異なります。たとえば、C++ では、前者が可変文字列で後者が可変文字列への明示的なポインタ (null ポインタでない場合) である と のどちらも使用できますが、Java では、暗黙的に可変文字列への参照 (null 参照でない場合) である のみを使用できます。
std::stringstd::string *StringBuilder
C++ のアプローチはより柔軟ですが、非参照を使用すると、少なくとも継承が使用されている場合は、オブジェクト スライスなどの問題が発生する可能性があります。オブジェクトが参照型に属する言語では、プログラマーからいくつかのオプションが削除されるという代償を払って、これらの問題は自動的に回避されます。
参照の再バインドとエイリアシング
ほとんどのプログラミング言語では、参照型の変数を変更して別のオブジェクトを参照すること、つまり変数を別のオブジェクトに再バインドすることが可能です。
たとえば、次の Java コードでは、
クラス Foo { public int a ; }
Foo a = new Foo (); Foo b = a ; a . prop = 3 ; a = new Foo (); a . prop = 1 ;
Fooは参照型で、 にはa最初に新しいオブジェクトの参照が割り当てられ、 はb同じオブジェクト参照に割り当てられます。aつまり、 と同じオブジェクトにバインドされるため、 を介して変更され、aにも表示されますb。その後、 にはa別の新しいオブジェクトへの参照が割り当てられ (再バインド)、 とaはb異なるオブジェクトを参照するようになります。最後に、 は、そのフィールドが値 であるa2 番目のオブジェクトを参照し、 は、そのフィールドが値 である1 番目のオブジェクトを参照します。
prop1bprop3
ただし、C++ などでは、「参照型」という用語はエイリアスを意味するために使用され、参照型の変数は元のオブジェクトへのエイリアスであるため、一度作成されると再バインドすることはできません。
構造体Foo { int a ; };
Foo a ; a . prop = 1 ; Foo & b = a ; Foo c = a ; a . prop = 3 ;
C++ では、すべての非参照クラス型は値セマンティクスを持ちます。上記の例では、bは の参照 (エイリアス) として宣言されておりa、すべての目的において、aと はb同じものです。 を再バインドして別のものにすることはできませんb。上記の例を実行すると、aとは であるb同じFooオブジェクトですが、はであるオリジナルのコピーです。
prop3caprop1
C#では、値型と参照型の区別とは別に、参照変数と呼ばれる別の概念もあります。[3]参照変数は、一度宣言されバインドされると、元の変数のエイリアスとして動作しますが、参照代入演算子を使用して別の変数に再バインドすることもできます= ref。変数自体は、値型と参照型を含む任意の型にすることができます。つまり、参照型の変数を参照(エイリアス)で関数に渡すことで、オブジェクト自体(変更可能な場合)に加えて、参照型変数が指すオブジェクトも変更できます。
不変データ型
オブジェクトが不変で、オブジェクトの等価性が同一性ではなく内容に基づいてテストされる場合、値型と参照型の区別はもはや明確ではありません。これは、オブジェクト自体は変更できず、全体として置換することしかできないためです (値型の場合)。または、別のオブジェクトを指す参照を使用して置換することしかできません (参照型の場合)。このような不変オブジェクトを変数間で渡す場合、オブジェクトの同一性が取得されない限り、オブジェクトがコピーされるか参照によって渡されるかどうかで目に見える違いはありません。何も変更できない関数型プログラミング言語 (Haskell など) では、このような区別はまったく存在せず、実装の詳細になります。
言語ごとの分類
参照
参考文献
- ^ Brown, Erik E. (2006). Windows Forms in Action. シェルターアイランド、ニューヨーク: マニング。p. 703。ISBN 978-1-932-39465-8。
- ^ Stephens, Rod (2014). C# 5.0 プログラマーズリファレンス. インディアナポリス、インディアナ州: John Wiley & Sons. p. 57. ISBN 978-1-118-84728-2。
- ^ 「参照変数」。
- ^ 「第 4 章 型、値、および変数」。docs.oracle.com。
- ^ 「C# キーワード」。docs.microsoft.com。
- ^ 「構造体とクラス — Swift プログラミング言語 (Swift 5.2)」。docs.swift.org。
- ^ 「クロージャ — Swift プログラミング言語 (Swift 5.2)」。docs.swift.org。
- ^ 「組み込み型 — Python 3.8.2rc1 ドキュメント」。docs.python.org。
- ^ 「ECMAScript® 2019 言語仕様」。www.ecma-international.org。
- ^ 「第24章 コアライブラリ」. caml.inria.fr .
- ^ 「変更可能なデータ構造」。caml.inria.fr。
- ^ 「PHP: 基礎」.
