- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
PHP 5.5.12。考虑一下:
<?php
$a = [ 'a', 'b', 'c' ];
foreach($a as &$x) {
$x .= 'q';
}
print_r($a);
正如预期的那样,输出:
Array
(
[0] => aq
[1] => bq
[2] => cq
)
现在考虑:
<?php
$a = [ 'a', 'b', 'c' ];
foreach(z($a) as &$x) {
$x .= 'q';
}
print_r($a);
function z($a)
{
return $a;
}
输出:
Array
(
[0] => aq
[1] => bq
[2] => cq
)
(!)但是等一下。 $a 没有通过引用传递。这意味着我应该从 z() 获取一个副本,该副本将被修改,并且 $a 应该保持不变。
但是当我们强制 PHP 发挥其写时复制魔法时会发生什么:
$a = [ 'a', 'b', 'c' ];
foreach(z($a) as &$x) {
$x .= 'q';
}
print_r($a);
function z($a)
{
$a[0] .= 'x';
return $a;
}
为此,我们得到了我所期望的:
Array
(
[0] => a
[1] => b
[2] => c
)
编辑:再举一个例子...
$a = [ 'a', 'b', 'c' ];
$b = z($a);
foreach($b as &$x) {
$x .= 'q';
}
print_r($a);
function z($a)
{
return $a;
}
这按预期工作:
Array
(
[0] => a
[1] => b
[2] => c
)
这有合理的解释吗?
最佳答案
错误67633已开放以解决此问题。该行为已被 this commit 更改努力消除 foreach 的引用限制。
<小时/>来自this 3v4l output您可以清楚地看到这种行为随着时间的推移而发生了变化:
已修复 this commit ;这将在 5.5.18 和 5.6.2 中提供。
在 PHP 5.5 之前,您的代码实际上会引发 fatal error :
Fatal error: Cannot create references to elements of a temporary array expression
当直接在 foreach
block 内使用函数结果时,这些版本不会执行写时复制。因此,现在使用原始数组,并且对元素的更改是永久性的。
我个人认为这是一个bug;写时复制应该发生。
在 phpng branch ,这很可能成为下一个主要版本的基础,常量数组是不可变的,因此只有在这种情况下才能正确执行写入时复制。像下面这样声明数组将会在 phpng 中出现同样的问题:
$foo = 'b';
$a = ['a', $foo, 'b'];
只有 Hack 能够正确处理目前的情况。
documented通过引用使用函数结果的方法是这样的:
$a = [ 'a', 'b', 'c' ];
foreach(z($a) as &$x) {
$x .= 'q';
}
print_r($a);
// indicate that this function returns by reference
// and its argument must be a reference too
function &z(&$a)
{
return $a;
}
为了避免更改原始数组,目前您有以下选择:
foreach
之前将函数结果分配给临时变量;关于php - 对于这种 PHP 按值调用行为有合理的解释吗?还是 PHP 的错误?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24772958/
我有一个曾经是 TreeView 控件的菜单,但现在我想让每个项目更加直观,并向树中的每个对象添加更多信息。 我的第一个意图是制作一个代表项目的用户控件,并在运行时将它们添加到面板中。这是一个好方法吗
我是 Docker 新手,想知道是否有可能(并且是一个好主意)在 Docker 容器中进行开发。我的意思是创建一个容器,执行 bash,安装和配置我需要的一切,然后开始在容器内进行开发。 容器将成为我
在 Java 中: Parent obj = new Child(); 我创建了一个 Parent 类型的对象。我假设我只能调用父类中定义的方法。因此,我无法调用 Child 中定义的“附加”方法或访
注意:我省略了其他两个阶段(V 和 W)的代码,示例中不需要。 我很确定,我这样处理“开”和“关”时间的方式并不是一种有效的方式。 我想使用查找表实现“开”和“关”脉动。计时器应与表的当前选定值进行比
当代码中包含 Java instanceof 运算符时,许多人会扬起眉毛并说这是禁忌。例如,在这个 other SO Q&A ,答案说: Note that if you have to use th
我是一名优秀的程序员,十分优秀!