今回の記事は、PHPの参照についてのまとめ第2弾。
変数を値渡しする場合と参照渡しする場合について、内部的にはどのような処理をしているのかを見ていく。
PHPのバージョン: 7.1.4
Contents
変数の値渡し
コード
1 2 3 4 5 6 7 |
<?php $a = "a"; $b = $a; $b = "abc"; var_dump($a); var_dump($b); |
実行結果
string(1) “a”
string(3) “abc”
string(3) “abc”
このとき、次のことが行われている。
順序 | 手順 | 内部処理 |
1 | $aに”a”を代入する。 | $aに”a”を保持するためのメモリー領域が確保される。 |
2 | $bに$aを代入する。 | $bを、$aが割り当てられているポインターに紐づける。($b分のメモリー領域は確保されていない。) |
3 | $bに”abc”を代入する。 | $bに”abc”を保持するためのメモリー領域が確保される。 |
この手順2の時点では、$bは$aのポインターを参照しているだけである。
そして手順3で$bに値が代入されるときに、$bにもメモリー領域が確保される。
このような仕組みをCopy-On-Write (COW)という。
手順3を終えた時点で、$aと$bそれぞれにメモリー領域が割り当てられ、そのメモリー領域がデータを保持している。
値をコピーする場合
変数と値がメモリーでどのように扱われているかを、簡略化して見ていく。
手順1: $a = “a”;
ポインター | 値 | 変数 |
1 | a | $a |
2 |
手順2: $b = $a;
ポインター | 値 | 変数 |
1 | a | $a, $b |
2 |
手順3: $b = “abc”;
ポインター | 値 | 変数 |
1 | a | $a |
2 | abc | $b |
手順3では、$bは「is_ref」という論理値(ブール値)によって、通常の変数か参照かを判断している。
$bは通常の変数であるため、新たにメモリー領域が用意され、値”abc”を持っている。
変数の参照渡し
コード
1 2 3 4 5 6 7 |
<?php $a = "a"; $b =& $a; $b = "abc"; var_dump($a); var_dump($b); |
実行結果
string(3) “abc”
string(3) “abc”
string(3) “abc”
このとき、次のことが行われている。
順序 | 手順 | 内部処理 |
1 | $aに”a”を代入する。 | $aに”a”を保持するためのメモリー領域が確保される。 |
2 | $bに$aに対する参照を代入する。 | $bを、$aが割り当てられているポインターに紐づける。($b分のメモリー領域は確保されていない。) |
3 | $bに”abc”を代入する。 | $bの紐づけられているポインターのメモリー領域に”abc”を保持する。 |
この手順2と3では、$aと$bそれぞれが同じポインターに紐づけられている。
そのため、$aと$bは同じ値を持つことになる。
参照をコピーする場合
変数と値がメモリーでどのように扱われているかを、簡略化して見ていく。
手順1: $a = “a”;
ポインター | 値 | 変数 |
1 | a | $a |
2 |
手順2: $b =& $a;
ポインター | 値 | 変数 |
1 | abc | $a, $b |
2 |
手順3: $b = “abc”;
ポインター | 値 | 変数 |
1 | abc | $a, $b |
2 |
手順3では、$bは「is_ref」という論理値(ブール値)によって、通常の変数か参照かを判断している。
$bは参照であるため、ポインター1の値は値”abc”に上書きされる。