phpの参照返値
ローカル変数を参照返値とすると、かならず実値辺値となります。ローカル変数はその関数のreturnで無効となりますから、このような実装は利にかなっているとも言えます。
関数宣言で&を付加しないと、返値領域へのテンポラリ変数に実値として設定され、それを参照として$aに設定するわけですが、しかしテンポラリ変数はtest()終了で無効となるため、実値として設定され、しかも無効になる故、新規にhogeを確保し、それにリンクします(refcount=1)。
<?php $a = &test(); xdebug_debug_zval('a'); function &test() { $b = "hoge"; return $b; } ?> [root@localhost test]# php a.php a: (refcount=1, is_ref=0)='hoge'グローバル(静的変数)では、期待する参照辺値となります。
<?php $b = "hoge"; $a = &test(); xdebug_debug_zval('a'); function &test() { global $b; return $b; } ?> [root@localhost test]# php a.php a: (refcount=2, is_ref=1)='hoge'参照辺値とする場合、呼び出し/関数宣言で&を追加する必要があります。呼び出しの&は、結果の代入時の扱いで、関数宣言の&は、返り値領域に設定する時の取り扱いと解釈すればと思います。
関数宣言で&を付加しないと、返値領域へのテンポラリ変数に実値として設定され、それを参照として$aに設定するわけですが、しかしテンポラリ変数はtest()終了で無効となるため、実値として設定され、しかも無効になる故、新規にhogeを確保し、それにリンクします(refcount=1)。
<?php $b = "hoge"; $a = &test(); xdebug_debug_zval('a'); function test() { global $b; return $b; } ?> [root@localhost test]# php a.php a: (refcount=1, is_ref=0)='hoge'呼び出しで&を付けないと、実値辺値となります。&test()の返値領域のテンポラリ変数へ参照としての$bを設定します。それを実値として$aに設定します。テンポラリ変数のリンク先は$b = "hoge"のhogeです。従ってテンポラリ変が無効になっても、リンク先が$b = "hoge"故、$aも$bのhogeをリンクしていて、refcount=2となっています。
<?php $b = "hoge"; $a = test(); xdebug_debug_zval('a'); function &test() { global $b; return $b; } ?> [root@localhost test]# php a.php a: (refcount=2, is_ref=0)='hoge'