按引用分配错误
前几天我遇到了这个看似非常简单的问题 如何在不引用$array 1的情况下更改$array 2中的值?然而,我研究得越多,就越奇怪,这似乎确实按预期运行。在此之后,我开始研究从以下输出生成的操作码。
$array1 = array(2, 10);
$x = &$array1[1];
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Outputs 22
这对我来说似乎很疯狂,因为array2应该只是array1的副本,而发生在一个数组上的任何事情都不应该影响另一个数组的内容。当然,如果您注释掉第二行,最后一行将像预期的那样回显出10行。
再往前看,我可以找到一个很酷的网站,向我展示PHP使用Vulcan Logic Dumper生成的操作码。这是上述代码生成的操作码。
Finding entry points
Branch analysis from position: 0
Return found
filename: /in/qO86H
function name: (null)
number of ops: 11
compiled vars: !0 = $array1, !1 = $x, !2 = $array2
line # * op fetch ext return operands
---------------------------------------------------------------------------------
3 0 > INIT_ARRAY ~0 2
1 ADD_ARRAY_ELEMENT ~0 10
2 ASSIGN !0, ~0
4 3 FETCH_DIM_W $2 !0, 1
4 ASSIGN_REF !1, $2
5 5 ASSIGN !2, !0
6 6 ASSIGN_DIM !2, 1
7 OP_DATA 22, $6
8 8 FETCH_DIM_R $7 !0, 1
9 ECHO $7
10 > RETURN 1
这些操作码在这里没有很好的记录 http://php.net/manual/en/internals2.opcodes.php 但我相信在英语中,操作码正在执行以下操作。按行...对我来说可能比任何人都多。
- 第 3 行:我们使用数组的第一个值初始化数组,然后向其添加 10,然后再将其分配给 $array 1。
- 第 4 行:获取只写?值,并通过引用$x来分配它。
- 第 5 行:将 $array 1 设置为 $array 2。
- 第 6 行:获取数组索引 1。od_data我猜把它设置为22,尽管6美元永远不会返回。OD_DATA绝对没有文档,也没有被列为我看过的任何地方的操作码。
- 第 8 行:从 $array 1 的索引 1 中获取只读值并将其回显出来。
即使通过操作码工作,我也不确定哪里出了问题。我有一种感觉,缺乏关于操作码的文档,以及我对使用它们的经验不足,可能会让我无法弄清楚哪里出了问题。
编辑1:
正如 Mike 在第一个注释数组中指出的那样,引用状态在复制时会保留。这里可以看到文档以及它链接到 http://php.net/manual/en/language.types.array.php#104064 的数组文章中的一个位置。这足够有趣并不被认为是警告。如果这是真的,我感到惊讶的是,此代码的引用状态不会像您预期的那样保留。
$array1 = array(2, 10);
$x = &$array1;
$array2 = $array1;
$array2[1] = 22;
echo $array1[1]; // Output is 10
因此,似乎只有在您尝试通过引用分配单个元素时才会发生这种情况,从而使此功能更加混乱。
为什么 php 只在单独分配数组索引时保留它们的状态?
编辑2:
我今天使用HHVM进行了一些测试,HHVM以您认为的方式处理代码的第一个片段。我喜欢PHP,但HHVM比Zend引擎看起来越来越好。