Php 为什么数组元素更改时,按值分配给数组元素的变量(在先前按引用分配之后)会更改?

Php 为什么数组元素更改时,按值分配给数组元素的变量(在先前按引用分配之后)会更改?,php,arrays,reference,Php,Arrays,Reference,当我运行代码blow时: $var[0] = 'a'; $tmp = $var; $var[0] = 'b'; var_dump($tmp); 输出为: array(1) { [0]=> string(1) "a" } 当我添加一行时,如下所示: $var[0] = 'a'; $foo = & $var[0]; # added line $tmp = $var; $var[0] = 'b'; var_dump($tmp); 输出变为: array(1) { [0]=>

当我运行代码blow时:

$var[0] = 'a';
$tmp = $var;
$var[0] = 'b';
var_dump($tmp); 
输出为:

array(1) { [0]=> string(1) "a" }
当我添加一行时,如下所示:

$var[0] = 'a';
$foo = & $var[0]; # added line
$tmp = $var;
$var[0] = 'b';
var_dump($tmp); 
输出变为:

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

如果我通过引用数组的元素
$var[0]
来分配变量
$foo
,那么通过值分配给数组
$var
的变量
$tmp
是否应该这样更改?为什么会发生这种情况?

这是,页面上的其中一个选项实际上提到了这种特定行为。

免责声明:我无法找到明确的参考,所以我在这里主要是推断

一个常规的参考可以通过符号表工作。创建变量和值时,它们都存储在本地符号表中,如下所示:

$foo = "bar";

+--------+-------+
| symbol | value |
+--------+-------+
| $foo   | "bar" |
+--------+-------+
创建引用时,只需将相同值的另一个符号添加到表中:

$bar =& $foo;

+------------+-------+
| symbol     | value |
+------------+-------+
| $foo, $bar | "bar" |
+------------+-------+
数组键的存储方式不同,但:

$var[0] = 'a';

+--------+-----------------+
| symbol | value           |
+--------+-----------------+
| $var   | array(0 => 'a') |
+--------+-----------------+
符号表中有一个条目用于
$var
,但数组中的值在符号表中没有单独引用。当创建对值
'a'
(存储在
$var[0]
中)的引用时,我推断必须发生的是,值
'a'
与数组
$var
分离,
$var[0]
本身成为对存储
'a'
的新位置的引用:

$foo =& $var[0];

+--------+------------------+
| symbol | value            |
+--------+------------------+
| $var   | array(0 => %REF) |
| $foo   | %REF             |
| %REF   | 'a'              |
+--------+------------------+
我猜符号表的内部实现不允许创建对数组键的直接引用,因此这是创建对数组元素引用的唯一方法

因此,当将
$var
复制到
$tmp
时,引用将与之一起复制:

$tmp = $var;

+--------+------------------+
| symbol | value            |
+--------+------------------+
| $var   | array(0 => %REF) |
| $foo   | %REF             |
| %REF   | 'a'              |
| $tmp   | array(0 => %REF) |
+--------+------------------+
然后,当更改
$var[0]
引用的值时,它会更改
%REF
的值,
$tmp
$var
都引用了该值

正如我所说,这可能是对内部发生的事情的准确解释,也可能不是,但它说明了原理。

请注意,各种“传递-*”术语只适用于函数参数。这里没有传递变量,只有赋值。