bravewood の日記

2013-03-07

PHPは代入と参照の違い 22:30 PHPは代入と参照の違いを含むブックマーク

http://ameblo.jp/nikko-inma/entry-11122429825.html

http://b.hatena.ne.jp/entry/ameblo.jp/nikko-inma/entry-11122429825.html

ふむふむ、なになに、PHPはクソ言語で、C++VBもクソで、

きっちり書きたいときはC
きっちり書きたいときはC
きっちり書きたいときはC

イスから転げ落ちるわ!!!


ちょっとこれはPHPerとしては突っ込まざるを得ない。

いつ突っ込むかって?

今でしょ!


とりあえず上記サイトで書かれてるサンプルじゃあ代入と参照が深く理解できないだろうってこともあり、その部分補足してみよう。


まずサンプルプログラム

<?php
    

$a = 1;
xdebug_debug_zval( 'a' );


$b = $a; //これはただの値の代入(ただしこので時点でbの変数コンテナは出来ない(copy on write))
xdebug_debug_zval( 'a' );
xdebug_debug_zval( 'b' );

$b = 111; //bの値を変えるとaの参照カウント(refcount)が1減って、新しくbの変数コンテナが作られる。
xdebug_debug_zval( 'a' );
xdebug_debug_zval( 'b' );


echo "----------------ここまで代入のみ、ここから参照(&)使うよ----------------\n";


$x = 1;
xdebug_debug_zval( 'x' );

$y = &$x; //yはxの参照。ただの代入と違うのは、is_ref=1になること。
xdebug_debug_zval( 'x' );
xdebug_debug_zval( 'y' );


$y = 222; //yを変えると、参照先のxの値が変わるよ。
xdebug_debug_zval( 'x' );
xdebug_debug_zval( 'y' );



echo "----------------そんじゃあ配列で参照使ってみるよ----------------\n";

$ary = array( 1, 2, 3 );
xdebug_debug_zval( 'ary' );

$ref = &$ary[1]; //refは$ary[1]の参照を使うからis_ref=1になるよ
xdebug_debug_zval( 'ary' );
xdebug_debug_zval( 'ref' );


$ref = 333; //refを変えると、参照先の$ary[1]の値が変わるよ。
xdebug_debug_zval( 'ary' );
xdebug_debug_zval( 'ref' );



次に実行結果

C:\Windows\System32>php -v
PHP 5.4.7 (cli) (built: Sep 12 2012 23:48:31)
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans

C:\Windows\System32>php C:\Users\bravewood\Desktop\test.php
a: (refcount=1, is_ref=0)=1
a: (refcount=2, is_ref=0)=1
b: (refcount=2, is_ref=0)=1
a: (refcount=1, is_ref=0)=1
b: (refcount=1, is_ref=0)=111
----------------ここまで代入のみ、ここから参照(&)使うよ----------------
x: (refcount=1, is_ref=0)=1
x: (refcount=2, is_ref=1)=1
y: (refcount=2, is_ref=1)=1
x: (refcount=2, is_ref=1)=222
y: (refcount=2, is_ref=1)=222
----------------そんじゃあ配列で参照使ってみるよ---------------
ary: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=1, 1 => (refcount=1, is_ref=0)=2, 2 => (refcount=1, is_ref=0)=3)
ary: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=1, 1 => (refcount=2, is_ref=1)=2, 2 => (refcount=1, is_ref=0)=3)
ref: (refcount=2, is_ref=1)=2
ary: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=1, 1 => (refcount=2, is_ref=1)=333, 2 => (refcount=1, is_ref=0)=3)
ref: (refcount=2, is_ref=1)=333

f:id:bravewood:20130307224850p:image


参考サイトからの抜粋


参照カウント法の原理

http://php.net/manual/ja/features.gc.refcounting-basics.php

変数を他の変数名に代入すると、refcount が増加します。 
(中略)
この時、refcount は 2 です。なぜなら、同じ変数コンテナが a と b にリンクされるからです。 

代入演算子

http://php.net/manual/ja/language.operators.assignment.php

参照による代入とは、両方の変数が同じデータを指すようにするということです。 データのコピーは発生しません。 


少し説明すると

f:id:bravewood:20130307222459p:image

f:id:bravewood:20130307225351p:image





忙しい人のためのまとめ

  • $ref = &$array[1]; も $b = &$a; も本質的には同じこと
  • 参照による代入とは、両方の変数が同じデータを指すようにするということ
  • var_dumpじゃ参照関係が見えにくい
  • xdebugのxdebug_debug_zvalを使うといい



そんなわけでPHPはクソ!!

bravewood the PHPer

トラックバック - http://d.hatena.ne.jp/bravewood/20130307