Why does a variable assigned by value to an array element (after an earlier assignment by reference) change when the array element changes?

When I run a code hit:

$var[0] = 'a'; $tmp = $var; $var[0] = 'b'; var_dump($tmp); 

conclusion:

 array(1) { [0]=> string(1) "a" } 

When I add the line as follows:

 $var[0] = 'a'; $foo = & $var[0]; # added line $tmp = $var; $var[0] = 'b'; var_dump($tmp); 

the output will be:

 array(1) { [0]=> &string(1) "b" } 

If I assign the variable $foo reference to an element of the array $var[0] , is the variable $tmp assigned the value for the array $var that should change like this? Why is this happening?

+6
source share
2 answers

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.

+3
source

This is cited in the docs , one of the comments actually mentions this particular behavior.

+2
source

Source: https://habr.com/ru/post/909240/


All Articles