Disclaimer: I could not find an explicit link for this, so I basically conclude here.
A regular link works through a character table. When creating a variable and value, they are stored in the local symbol table as follows:
$foo = "bar"; +--------+-------+ | symbol | value | +--------+-------+ | $foo | "bar" | +--------+-------+
When a link is created, it simply adds another character for the same value to the table:
$bar =& $foo; +------------+-------+ | symbol | value | +------------+-------+ | $foo, $bar | "bar" | +------------+-------+
Array keys are stored differently:
$var[0] = 'a'; +--------+-----------------+ | symbol | value | +--------+-----------------+ | $var | array(0 => 'a') | +--------+-----------------+
There is an entry in $var
in the symbol table, but the values ββinside the array are not specified individually in the symbol table. What I do should happen when creating a reference to the value of 'a'
(stored in $var[0]
), is that the value of 'a'
is separated from the array of $var
, and $var[0]
itself becomes a link to a new location where 'a'
stored:
$foo =& $var[0]; +--------+------------------+ | symbol | value | +--------+------------------+ | $var | array(0 => %REF) | | $foo | %REF | | %REF | 'a' | +--------+------------------+
I assume that the internal implementation of the symbol table does not allow direct links to array keys, so this is the only way to create a link to an array element.
Therefore, when copying $var
to $tmp
link is copied with it:
$tmp = $var; +--------+------------------+ | symbol | value | +--------+------------------+ | $var | array(0 => %REF) | | $foo | %REF | | %REF | 'a' | | $tmp | array(0 => %REF) | +--------+------------------+
Then, when the value of $var[0]
changes, it changes the value of %REF
, referenced by both $tmp
and $var
.
As I said, this may or may not be an accurate explanation of what is going on inside, but it illustrates the principle.