移転しました。

PHPの参照渡しは関数の引数だけじゃない

PHPの参照渡しについて。参照渡しについて説明しているサイトでは圧倒的に関数の引数を例にしていることがほとんど。例えば以下のような感じ。

<?php
$v = "default";
rewrite($v);
print $v;

function rewrite(&$arg) {
    $arg = "HelloWorld";
}

これで「HelloWorld」と出力される。$vを直接変更していないのに、rewrite関数内での変更が$vに対して有効になっていると解く。関数の引数に「&」を付けなければ上書きされることはない(値渡し)。
最初はこれが一番判り易いけれど、もう一歩、変数代入の参照渡しと関数戻り値の参照渡しにも触れて欲しいところ。特に関数戻り値の参照渡しについて触れているサイトが本当に少ない。
変数代入の参照渡しというのは以下のコードのような場合。

<?php
$a = "default";
$b =& $a;
$b = "HelloWorld";
print $a;

これで「HelloWorld」と出力される。2行目で$aの持つ参照先が$bに渡されているために、$aの変更と$bの変更は同義となっているということ。因みにJavaでは通常(プリミティブや不変オブジェクトなどの場合は異なる)このように参照渡しで代入される。
もうひとつ。関数の戻り値の参照渡しについて。

<?php
class HelloWorld {
    var $value = "default";
    function &getValue() {
        return $this->value;
    }
}

$helloWorld = new HelloWorld();
$v =& $helloWorld->getValue();
$v = "HelloWorld";
print $helloWorld->value;

これで「HelloWorld」と出力される。関数「&getValue」の「&」とメソッド実行の戻り値「=& $helloWorld->getValue();」の「&」のどちらが抜けても参照渡しにはならない。その場合は値渡しとなり「default」と出力される。
オープンソースPHPコード(PEARとか)では上の例のどれも頻繁に使われているけれど、説明しているサイトには関数の引数の説明しかないので、最初見たときは何のことか判らなかった(想像はできたけど)。
参照渡しを調べていて納得できない人がこのエントリに辿り着けるように、「アンパサンド」とか「全角の&」とかをこの文章に含めておこう(スパム行為?)。
補足として関数の値渡しと参照渡し、どちらが速い?

参照渡し・値渡しの違いは、値が変更された時に初めて起こる

というのは知らない人が多いかもしれない。