オブジェクトと同じくHashTableの複製はせずにリファレンスカウンタを増やすだけになってたんですね。
ちょっとテストしてみた結果はこうなりました。スタイルシートのせいで表が見にくいのは勘弁してください。
個人的に結果2b (PHP5) での$c、結果3a (PHP4) での$bの値は予想外でした。
2bは$aに自身が追加される前にSEPARATE_ZVAL_IF_NOT_REFマクロでポインタを分離されているためと思われますが、確証は持てません。(ZendEngineのここらへんの部分をよく見たわけではないので)
3aは$aが$cに参照として追加される際にis_refフラグが立ったためですね。
普段はフラットリストからツリーを作成したり、再帰的なデータ構造を作成するときは明示的に参照を使っているので気付きませんでした。こういう仕様変更もあったのかと、興味深かったです。
しかしこの事実が役に立つかといえばまた微妙なわけで... (プログラミングのためではなく処理の高速化とメモリ管理の効率化のためにこうなったんだと思います)
code | PHP 4.4.7 | PHP 5.2.4 |
---|---|---|
テスト1
<?php $a = array(1); $b = array(2); $a[] = $a; $b[] = $a; var_dump($a, $b); ?> | 結果1a
array(2) { [0]=>int(1) [1]=>array(1) { [0]=>int(1) } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(1) { [0]=>int(1) } } } | 結果1b
array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } |
テスト2
<?php $a = array(1); $b = array(2); $c = array(3); $c[] = $a; $a[] = $a; $b[] = $a; var_dump($a, $b, $c); ?> | 結果2a
array(2) { [0]=>int(1) [1]=>array(1) { [0]=>int(1) } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(1) { [0]=>int(1) } } } array(2) { [0]=>int(3) [1]=>array(1) { [0]=>int(1) } } | 結果2b
array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } array(2) { [0]=>int(3) [1]=>array(1) { [0]=>int(1) } } |
テスト3
<?php $a = array(1); $b = array(2); $c = array(3); $c[] = &$a; $a[] = $a; $b[] = $a; var_dump($a, $b, $c); ?> | 結果3a
array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } } array(2) { [0]=>int(3) [1]=>&array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } } | 結果3b
array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } array(2) { [0]=>int(2) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } } array(2) { [0]=>int(3) [1]=>&array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>array(2) { [0]=>int(1) [1]=>*RECURSION* } } } } |