PHP で不要なときに参照割当てすることはなぜダメなのか?

参照割当てが不要なときに、参照割当てを実施することは良いことではありません。

この資料ではその理由を説明します。この資料の内容を理解するためには、zval という内部データ構造について理解している必要がありますので、 「PHP5 のオブジェクトに関するよくある間違いとメモリ管理 (コピーオンライト) とオブジェクトの取り扱い」についても 合わせて参照してください。

必要ないときに参照割当てをすると、ダメな例

次のコードを見てください。

<?php
$a = 'foo';
$b = $a;
$c =& $a;
?>

一行ずつ見て行きましょう。$a = 'foo' のラインで zval は次のようになります。

'a' => zval ( type => IS_STRING, value.lval='foo', is_ref = 0, refcount = 1)

次の行、$b = $a でラベル 'b' はもとの zval と関連付けされます。

'a' => zval ( type => IS_STRING, value.lval='foo', is_ref = 0, refcount = 2)
'b' /

ここまでは問題ありません。

問題はその次です。 $c =& $a で zval はどうなるでしょうか。

元の zval は既に参照型ではない (is_ref = false) とマークされており、refcount が 1 より大きいため、$c =& $a としたからと言って、 直ちに is_ref = true と書き換えることは出来ません。もしそうしてしまうと、$b の変更が $a に影響するなどして別の問題となることでしょう。

この問題を解決するため、PHP エンジンは zval のコピーを作成します。

'a' => zval ( type => IS_STRING, value.lval='foo', is_ref = 1, refcount = 2)
'c' /
'b' => zval ( type => IS_STRING, value.lval='foo', is_ref = 0, refcount = 1)

このように結局、値を変更していないにもかかわらず元の文字列のコピーを持つことになり、メモリのムダが発生します。

従って、後で違う変数で値を変更するということに備えるなどの理由で、必要の無いときに参照で値を割り当てることは良いことではありません。

ここまでお読みいただき、誠にありがとうございます。SNS 等でこの記事をシェアしていただけますと、大変励みになります。どうぞよろしくお願いします。

© 2024 Web/DB プログラミング徹底解説