変数の参照 (call by reference)
変数の代入
PHPでは通常、変数の代入はコピー(クローン)が渡されます。
(PHP5ではインスタンスは参照渡し)
PHP:
-
$var1 = 1;
-
$var2 = $var1;
-
$var1 += 10;
-
$var2 += 20;
-
-
// VAR1:11 VAR2:21
-
print "VAR1:$var1 VAR2:$var2";
$var1、$var2、それぞれ独立しています。
参照の代入
参照を代入するには、参照演算子=&を使います。
PHP:
-
$var1 = 1;
-
$var2 =& $var1;
-
$var1 += 10;
-
$var2 += 20;
-
-
// VAR1:31 VAR2:31
-
print "VAR1:$var1 VAR2:$var2";
さっきとは違い、出力文で$var1と$var2が同じである事が分かります。これは、2行目で変数$var1の参照を代入している為です。参照とは変数が持っているアドレス(実際のデータへの住所)の事です。2行目の代入により、$var2が$var1を参照しているのではなく、2つは同じデータを参照しているのです。
PHP:
$var1を削除したのに、$var2は残っています。var2はvar1と同じ場所にデータを持つ、別名(エイリアス)の変数と捕らえる事ができます。参照の削除とは、変数名と実際のデータの関係性を破棄することにすぎません。つまり、以下は参照渡しになりません。
PHP:
-
$var = 100;
-
$ref =& $var;
-
-
// エラー
-
$ref =& 200;
-
-
function test() {
-
return 200;
-
}
-
// 無効な参照渡し
-
$ref =& test();
通常の代入で、わざわざ参照を使う必要はありません。
大きな配列やインスタンスを扱う場面で効果を発揮します。
関数で参照を返す
関数の戻り値を参照にする事もできます。関数名の前に&を付けて、戻り値が参照である事を明示しておきます。返ってきた参照を代入する時も同様に&を付けます。この場合、どちらの&が欠けても参照渡しにはなりません。
PHP:
関数に参照を渡したい時は、必ず定義する時に&を付けておく必要があります。
引数に&をつけて関数を呼ぶ方法は、今後廃止される予定です。
PHP:
-
// 正
-
function func(&$arg) {}
-
func($arg);
-
-
// 誤
-
function func($arg) {}
-
func(&$arg);
インスタンス生成時の注意点
PHP4でコンストラクタ定義で&を付ける必要はありません。ただし、インスタンス生成時にnewがコピーを返すので注意が必要です。
PHP:
-
class Test {
-
var $value = 'foo';
-
-
function Test() {
-
$GLOBALS["test"] =& $this;
-
}
-
function set($value) {
-
$this->value = $value;
-
}
-
function display() {
-
}
-
}
-
-
$obj = new Test();
-
$obj->set('bar');
-
$obj->display(); // bar
-
$test->display();// foo
-
-
$obj =& new Test();
-
$obj->set('bar');
-
$obj->display(); // bar
-
$test->display();// bar
インスタンスの代入
PHP5からインスタンスの扱いはJAVA同様に参照となります。
PHP:
-
$obj =& new Class();
-
// PHP4
-
$ref_obj =& $obj;// 2つは同じ
-
$copy_obj = $obj;// 2つは独立
-
-
// PHP5
-
$ref_obj = $obj;// 2つは同じ
-
$copy_obj = clone $obj;// 2つは独立