When I run the code blow:
$var[0] = 'a';
$tmp = $var;
$var[0] = 'b';
var_dump($tmp);
the output is:
array(1) { [0]=> string(1) "a" }
When I add a line as follows:
$var[0] = 'a';
$foo = & $var[0]; # added line
$tmp = $var;
$var[0] = 'b';
var_dump($tmp);
the output becomes:
array(1) { [0]=> &string(1) "b" }
If I assign a variable $foo
by reference to an array's element $var[0]
, is the variable $tmp
assigned by value to the array $var
supposed to change like that? Why does this happen?
Disclaimer: I have not been able to find an explicit reference for this, so I'm mostly inferring here.
A regular reference works through the symbol table. When creating a variable and a value, both are stored in the local symbol table like so:
$foo = "bar";
+--------+-------+
| symbol | value |
+--------+-------+
| $foo | "bar" |
+--------+-------+
When a reference is created, this simply adds another symbol for the same value to the table:
$bar =& $foo;
+------------+-------+
| symbol | value |
+------------+-------+
| $foo, $bar | "bar" |
+------------+-------+
Array keys are stored differently though:
$var[0] = 'a';
+--------+-----------------+
| symbol | value |
+--------+-----------------+
| $var | array(0 => 'a') |
+--------+-----------------+
There's an entry in the symbol table for $var
, but the values inside the array are not individually referenced in the symbol table. What I infer must be happening when creating a reference to the value 'a'
(stored in $var[0]
) is that the value 'a'
is separated from the array $var
and $var[0]
itself becomes a reference to the new location of where 'a'
is stored:
$foo =& $var[0];
+--------+------------------+
| symbol | value |
+--------+------------------+
| $var | array(0 => %REF) |
| $foo | %REF |
| %REF | 'a' |
+--------+------------------+
I guess that the internal implementation of the symbol table does not allow to create direct references to array keys, therefore this is the only way to create a reference to an array element.
So when copying $var
to $tmp
, the reference is copied with it:
$tmp = $var;
+--------+------------------+
| symbol | value |
+--------+------------------+
| $var | array(0 => %REF) |
| $foo | %REF |
| %REF | 'a' |
| $tmp | array(0 => %REF) |
+--------+------------------+
Then, when changing the value $var[0]
refers to, it changes the value of %REF
, which both $tmp
and $var
refer to.
As I said, this may or may not be an accurate explanation of what's happening internally, but it illustrates the principle.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With