[PHP-users 10606] Re: 1つのインスタンスを参照する2つの変数のチェック方法
KUROSAWA Akira
php-users@php.gr.jp
Mon, 07 Oct 2002 21:30:45 +0900
黒澤です。
WADA Masashi wrote:
>>>上記の check_reference() を利用した次のコードを実行してみると、
>>>
>>>$a = 1;
>>>$b = $a;
>>>print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
>>>$a = 2;
>>>print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
>>>
>>>結果は
>>>
>>>1, 1 : ref.
>>>2, 1 : not ref.
>>>
>>>となります(テスト環境はPHP4.1.2/4.2.2)。
>>
>>多分、タイプミスだと思うんですが、2行目の「$b = $a」は「$b =& $a」ですよね。
>>だとすれば、これは期待通りの動作です。
>
>
> いえ、「$b = $a」です。
大変失礼致しました。
和田さんがせっかく書いてくれたコードを検証もせず、コードを見ただけで
回答してしまいました。スイマセン。m(_ _)m
実際に動かしてみましたが、この結果にはちょっと驚きました。
(後半の検証結果をご参照ください)
> メモリの有効利用と高速化を目指して、PHP4から Reference Counting
> が導入されています。例えば次のようなコードについて考えてみます。
>
> $a = 1; //---(1)
> $b = $a; //---(2)
> $a = 2; //---(3)
> $b = 3; //---(4)
>
> (1).$a はメモリ上に確保された 1 という値を参照します。
> (2)."="は代入演算子ですから、本来なら $b に 1 という値がコピー
> されるはずです。しかしPHPの内部では $b は(1)で確保された 1
> を参照するだけに留めています。
> (3).新たな値 2 がメモリ上に用意されて、$a はこちらを参照します。
> $b は(1)で確保された 1 を参照したままです。
> (4).新たな値 3 がメモリ上に用意されて、$b はこちらを参照します。
> (1)で確保された 1 は誰も参照しなくなったのでメモリが解放さ
> れます。
>
> というのが Reference Counting の考え方です。私の理解が間違ってい
> るかもしれないので、Zend のページで確認してみて下さい。
> → http://www.zend.com/zend/art/ref-count.php
>
> プログラマーが「$b = & $a;」で直接指示するような Reference と
> は少し意味が違うので注意しましょう。
ご丁寧な説明、ありがとうございます。
Zendのページは解読に少し時間がかかりそうなので、後でゆっくり
読ませて頂きます。
>
(省略)
>
> それにしても
>
> $a = 1;
> $b = 1;
> print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
> $a = 2;
> print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
>
> の結果が
>
> 1, 1 : ref.
> 2, 1 : not ref.
>
> になるのはおもしろいですね。
何故こうなるのか検証してみました。
どうやら check_reference() のバグのようですね(^^;
check_referernce()関数内の2つのif文
if($var1 . "." == $var2)
if($var2 == $var1)
の比較演算子 "==" を "==="(イコール3つ)に変更すると期待通りの動きになる
ようです。
『文字列の変換』
http://www.php.net/manual/ja/language.types.string.php#language.types.string.conversion
数値として文字列が評価された時。。。 文字列の最初の部分により値が決まり
ます。
と書かれているので、$var1の後ろに付加されているはずのドットが無視されて
しまっている
ために例にあげて頂いたような動きになるようです。
で、修正後のソースで最初のソースを実行してみました。
$a = 1;
$b = $a;
print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
$a = 2;
print "$a, $b : ".(check_reference($a, $b) ? "ref.\n" : "not ref.\n");
結果は
1, 1 : not ref.
2, 1 : not ref
となりました。(^^;
んー、Reference Counting がプログラミング上どのように影響するのか
よくわからなくなってきました。(^^;
ご提示頂いたZendページを解読してまとめたいと思います。
(少々時間がかかると思いますが。。。)
ありがとうございました。
--
株式会社システムジェイ
システム開発グループ
黒澤 明 kurosawa@systemj.com