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とか)では上の例のどれも頻繁に使われているけれど、説明しているサイトには関数の引数の説明しかないので、最初見たときは何のことか判らなかった(想像はできたけど)。
参照渡しを調べていて納得できない人がこのエントリに辿り着けるように、「アンパサンド」とか「全角の&」とかをこの文章に含めておこう(スパム行為?)。
補足として関数の値渡しと参照渡し、どちらが速い?

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

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

9件のコメント

  1. はじめまして。
    戻り値の参照渡しについてご解説を読ませていただきました。
    お陰様で理解を深めることができました。
    一言お礼を述べたくてコメントさせていただきます。
    どうもありがとうございましたm(__)m

  2. こんにちは。
    お役に立てたのであれば嬉しい限りです。
    普通の会社で作成されたPHPコードと、PEARやオープンソースフレームワークなどを比べると、本当に「&」の量が全然違うので、PHPは参照渡しの理解がし難いのだろうなと感じています。

  3. はじめまして。phpの勉強を最近始めました。
    参照渡しとかわかったような気がします。
    分かり易い解説ありがとうございました。
    これからもよろしくお願いしますm(__)m

  4. こんにちは。分かり易いと言って頂けるなら、書いたほうとしても嬉しいです。ありがとうございます。

  5. 始めまして。参照渡しの理解が出来なくて困ってる時にこのブログに
    辿り着きました。
    メソッドに&を付ける時の意味がどうしても分からなくてもやもやして
    いたのですが、もやもやが解消する事が出来ました。
    お礼が言いたくて、書き込みました。
    有難うございました。

  6. 自分ひとりで主張しても聞いたこともないと馬鹿にされてしまう日々なので
    こういう記事は本当にありがたいです。

    社員よりもしらない人の日記の方が信頼できるという
    会社の体質かもしれませんが、とにかく感謝です。

  7. 今まで参照渡しを理解できず…

    やっと少し理解することが出来ました!

    ありふぁとうございます。

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です