PHP的foreach()如何在单个数组上成功嵌套?
How can PHP's foreach() be successfully nested on a single array?
考虑以下代码:
$a = [1, 2, 3];
foreach ($a as $x) {
foreach ($a as $y) {
echo "$x $y\n";
}
}
正如人们所期望的那样,它给出了以下结果:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
虽然对结果很满意,但我很惊讶它的工作原理,因为根据 manual,它依赖于数组的内部指针:
When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.
As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.
所以我们可以预期在第一个内部使用嵌套的 foreach
会共享相同的内部指针,并产生以下结果:
1 1
1 2
1 3
因为第一个foreach
会看到嵌套foreach
留下的内部指针的状态。
我可以想到两种可能的实际行为解释:
- PHP 手册错误/过时,PHP 使用单独的指针特定于每个
foreach
;
- 嵌套的
foreach
在内部触发了内存中数组的复制,因此它们每个都有自己的指针。
就我的文化而言,这在内部是如何运作的?
简答。 PHP确实在这种情况下复制了数组(即数组结构)。 Foreach 可以在各种情况下这样做,以防止出现此类问题。有些人认为 foreach always 复制数组,但事实并非如此(那样效率低下)。
我找到了一篇很棒的博客 post,它更详细地描述了这种行为:
PHP internals: When does foreach copy?
总结:
foreach
将复制数组 structure 当且仅当迭代
数组未被引用且引用计数 > 1
foreach
会
另外复制数组 values 当且仅当前一点
应用并通过引用完成迭代
考虑以下代码:
$a = [1, 2, 3];
foreach ($a as $x) {
foreach ($a as $y) {
echo "$x $y\n";
}
}
正如人们所期望的那样,它给出了以下结果:
1 1
1 2
1 3
2 1
2 2
2 3
3 1
3 2
3 3
虽然对结果很满意,但我很惊讶它的工作原理,因为根据 manual,它依赖于数组的内部指针:
When foreach first starts executing, the internal array pointer is automatically reset to the first element of the array. This means that you do not need to call reset() before a foreach loop.
As foreach relies on the internal array pointer, changing it within the loop may lead to unexpected behavior.
所以我们可以预期在第一个内部使用嵌套的 foreach
会共享相同的内部指针,并产生以下结果:
1 1
1 2
1 3
因为第一个foreach
会看到嵌套foreach
留下的内部指针的状态。
我可以想到两种可能的实际行为解释:
- PHP 手册错误/过时,PHP 使用单独的指针特定于每个
foreach
; - 嵌套的
foreach
在内部触发了内存中数组的复制,因此它们每个都有自己的指针。
就我的文化而言,这在内部是如何运作的?
简答。 PHP确实在这种情况下复制了数组(即数组结构)。 Foreach 可以在各种情况下这样做,以防止出现此类问题。有些人认为 foreach always 复制数组,但事实并非如此(那样效率低下)。
我找到了一篇很棒的博客 post,它更详细地描述了这种行为:
PHP internals: When does foreach copy?
总结:
foreach
将复制数组 structure 当且仅当迭代 数组未被引用且引用计数 > 1foreach
会 另外复制数组 values 当且仅当前一点 应用并通过引用完成迭代