参照
読み:さんしょう
外語:reference

 ある変数の別名を持った変数のこと。英語ではreference(リファレンス)という。
目次

概要
 プログラミング言語にもよるが、参照変数として定義された変数がもつ値は、一般に他のオブジェクトへのポインターである。
 Cのようにポインター渡しされた場合は、*演算子を使って各値を参照する必要があり、少し手間が増える。
 C++Javaなどのように参照渡しまたは参照の値渡しをした場合、その変数の別名が渡されるため、受け取った先では、それを元の変数そのもののように扱うことができる。

特徴

C/C++

C++から対応
 参照はC++で使えるようになった。Cでは使えない。
 Cの場合は値渡しの一種「ポインター渡し」のみに対応しており、参照渡しに対応していない。

宣言
 プログラミング言語にもよるが、C++の場合は、次の構文で宣する。
データ型 &参照の名前 = 元の変数名;
 参照変数はあくまで別名なので、宣言と同時に元の変数が代入されなければならない。宣言のみをすることはできない。
 そして例えば、int &rnを宣言し、このrnにnを代入すれば、rnはnの参照となり、rnに対する読み書きはnに対する読み書きになる。
int n;
int &rn1;            /* ERROR */
int &rn2 = n;        /* OK */

メリットとデメリット
 ポインター渡しの場合、受け取る側はポインター変数を宣言し、その内容は間接演算子(アスタリスク)を使って読み書きすることになる。
 一方、参照渡しの場合は、受け取る側が参照変数を宣言し、その内容は参照変数に対する読み書きで行なう。このため間接演算子を使う必要が無い。
 間接演算子が多くなるとソースが読みにくくなるが、そのような問題も回避できる。
 但し、呼ばれる側は簡潔になるという利点があるが、呼ぶ側は値渡しと区別が付かない(ポインター渡しなら&演算子を使うが、参照渡しでは何も付けない)ので、分かりにくくなるという問題点もある。

クラス
 C++で参照渡しが作られたのは、C++で追加されたクラスの実装を自然にするためである。特に、代入演算子などのオーバーロードやコンストラクターで頻繁に使われる。
 例えば、CやC++では、変数の代入が可能である。
x = y;
 C++で独自にクラスを作ったとき、この処理を実現するためには自前で処理を書く必要があり、これを実現するのに参照が必要となる。
class A
{
    int a;
    public:
    A &operator=(const int &n) { this->a = n; return *this; }
};
 このように宣言すれば、xとyがともにclass Aのインスタンスだとすると、x = y;という処理が可能になる。
 参照を使わず、ポインター渡しだけで書く場合、次のようになる。
class A
{
    int a;
    public:
    A *operator=(const int *p) { this->a = *p; return this; }
}

Java

プリミティブ型と参照型
 Javaの場合、変数はプリミティブ型(基本データ型)と参照型と二種類の型が存在する。プリミティブ型は予約語として全て小文字で始まる型であり、それ自体が具体的な値を持ち、またメソッドは持たない。具体的にはboolean/byte/char/short/int/long/float/doubleの8種類が該当し、それ以外は全て参照型である。
 参照型の変数は、具体的な値ではなく、newで生成されたオブジェクトへのポインター、つまりメモリー上のアドレスを持っている。int型でも配列int[]は参照型であるし、頻用するStringなどは代表的な参照型である。

参照
 Javaで参照型変数を定義すると、そのメモリー上には参照型のオブジェクトが作られる。そのオブジェクト内には、nullか、または実際のオブジェクトへのポインターが格納される。
 例えば次のように定義する。
 String str = "message";
 メモリー上には、"message" という文字列オブジェクトが用意され、またstrという名のString型オブジェクトが定義されて "message" という文字列オブジェクトへのポインターが格納される。
 String型変数は内容を書き換えることはできず、別の値に変更した場合はその新しい値が改めて文字列オブジェクトとして用意され、String型オブジェクトにはその新しい文字列オブジェクトへのポインターが格納される。この時元の "message" という文字列オブジェクトは未使用となり参照がなくなるが、このように参照がなくなったオブジェクトがガベージコレクションの対象となる。

Javaの参照渡し
 Javaではメソッドへの引数の渡し方は全て値渡しであり例外はない。参照の場合、参照値が値渡しされる参照の値渡しという渡され方をする。Javaでは意識する必要はないが、C/C++のポインター変数と同様にJavaの参照で格納されている値は参照値(reference values)というポインターであって、実際のオブジェクトを指し示す値である。
 Javaで参照の値渡しで受け取った変数を書き換えた場合、それがimmutableなクラスではない場合、呼び出し元にも影響を与える。従ってクラスを引数とすることで、このクラスを用いて同時に複数の値を返すことが可能である。一方、String型のようにimmutableなクラスの場合は、値を書き換えても呼び出し元には影響を与えない。

再検索