在foreach循环电流()的意外行为 [英] Unexpected behaviour of current() in a foreach loop
问题描述
下面是一个简单的循环
$list = array("A", "B", "C","D");
foreach ($list as $var) {
print(current($list));
}
输出(演示)
BBBB // Output for 5.2.4 - 5.5.0alpha4
BCD // Output for 4.4.1
AAAA // Output for 4.3.0 - 4.4.0, 4.4.2 - 5.2.3
问:
- 可以有人请解释怎么回事?
- 为什么我没有得到ABCD
- 即使数组的一个副本是由
的foreach
做我应该得到AAAA
,但没有得到,在当前PHP
稳定版
- Can someone please explain whats going on ?
- Why am i not getting ABCD
- Even if a copy of the array was made by
foreach
i should be gettingAAAA
but not getting that in the currentPHP
stable version
注*我知道我可以简单地使用打印是$ var
但是从PHP DOC
Note* I know i can simply use print $var
but the from PHP DOC
电流 - 返回当前数组中的元素
该电流()函数只是返回的目前正由内部指针指向的数组元素的值。它不以任何方式移动指针。如果超出了元素列表或数组的末尾内部指针指向是空的,当前的()返回FALSE。
current — Return the current element in an array The current() function simply returns the value of the array element that's currently being pointed to by the internal pointer. It does not move the pointer in any way. If the internal pointer points beyond the end of the elements list or the array is empty, current() returns FALSE.
更新1 - 新观察
感谢 丹尼尔·菲格罗亚 :只需通过包装电流
在函数中你会得到不同的结果。
Thanks to Daniel Figueroa : Just by wrapping current
in a function you get different result
foreach ( $list as $var ) {
print(item($list));
}
function item($list) {
return current($list);
}
输出(演示)
BCDA // What the hell
问:
- 为什么没有得到BBBB?
- 如何在函数包装目前影响
的foreach
输出? - 在哪里额外的A从何而来?
更新2
$list = array("A","B","C","D");
item2($list);
function item2($list) {
foreach ( $list as $var ) {
print(current($list));
}
}
输出(见演示)
AAAA // No longer BBBB when using a function
问:
- 什么是不同的运行函数中的循环和功能外运行它,因为你得到
AAAA
之外,BBBB
在大多数PHP版本的函数
- What is the different running a loop in a function and running it outside a function because you get
AAAA
outside andBBBB
in a function in most PHP version
推荐答案
为什么它与B'开始
由于5.2 的foreach
(可靠)推进前数组指针的 的循环体开始。又见 FE_RESET
运code。
Since 5.2 foreach
(reliably) advances the array pointer before the loop body starts. See also the FE_RESET
opcode.
$list = array("A", "B", "C","D");
foreach ($list as $var) {
break;
}
var_dump(current($list));
输出:
B
这可能与东西怎么 ZEND_OP_DATA
伪运code ++工程,(这是不是真的记录)。
This may have something to with how the ZEND_OP_DATA
pseudo opcode works (which isn't really documented).
为什么电流()
继续给予同样的价值?
Why does current()
keep giving the same value?
在的foreach
创建一个内部参考,你遍历数组。一旦循环,每当数组变量通过引用改性或通过内部,内部参考从可变通过使阵列结构(但不是元素)的拷贝关联。这个复制的值保留数组指针(它早先被环路初始化修改)。
Before the loop starts, foreach
creates an internal reference to the array that you're looping over. Once inside the loop, whenever the array variable is modified or passed by reference, the internal reference is disassociated from the variable by making a copy of the array structure (but not the elements). This copied value retains the array pointer (which had earlier been modified by the loop initialization).
此行为也表现出了更大的破坏性未设置()
操作:
This behaviour is also exhibited with a more destructive unset()
operation:
$list = array('A', 'B', 'C', 'D');
foreach ($list as $key => $val) {
echo $val;
unset($list[1], $list[2], $list[3]);
}
echo "\n", print_r($list, true), "\n";
输出:
ABCD
Array
(
[0] => A
)
传递循环变量的函数
这是另一个有趣的场景:
This is another interesting scenario:
$list = array('A', 'B', 'C', 'D');
function itm($arr)
{
return current($arr);
}
foreach ($list as $item) {
print itm($list);
}
var_dump(current($list));
输出:
BCDA
bool(false)
这时候,数组是按值传递,因此,其阵列结构被复制(而不是元素)到函数的 $改编
参数。不同于previous例如,有循环的内部参考和 $列表
符号之间没有解离,因为复制发生在函数范围内。
This time, the array is passed by value and thus its array structure is copied (not the elements) into the function's $arr
parameter. Unlike the previous example, there's no disassociation between the loop's internal reference and the $list
symbol because the copy takes place in the function scope.
的怎么样的最后一个A
?的
这是迄今为止的foreach
中最神秘的行为,只能在这些情况下见证。在最后的循环迭代,数组指针的看似的后退到第一个项目;似乎是因为在循环结束,这点显然超出了元素的末尾(你可以从输出的最后一行看到的)。
This is by far the most mystifying behaviour of foreach
and can only be witnessed under these circumstances. In the last loop iteration, the array pointer is seemingly rewound to the first item; seemingly because at the end of the loop it obviously points beyond the end of the elements (as you can see from the last line of the output).
这可能有一些做的 SWITCH_FREE
这是在结束时执行运算code一的foreach
。
那么,为什么把的foreach
在功能使它不同?
So why does placing foreach
in a function make it different?
遵守以下code:
function item2($arr)
{
foreach ($arr as $var) {
print(current($arr));
}
var_dump(current($arr));
}
$list = array("A","B","C","D");
item2($list);
输出:
AAAA
string(1) "A"
在这种情况下,内部参考在的foreach
与所述数组的副本初始化(因为它具有引用计数> 1),从而创建从一个立即解除关联在 $改编
符号。
In this case, the internal reference of the foreach
is initialized with a copy of the array (because it has a refcount > 1) and thus creates an immediate disassociation from the $arr
symbol.
它可以得到更糟?
当然!当你开始使用引用或嵌套多个的foreach
循环上相同的变量,你可以得到甚至whackier结果。
Of course! You can get even whackier results when you start using references or nest multiple foreach
loops on the same variable.
那么如何才能得到一致的结果?
使用 迭代器
或不依赖于得到一个一致的值从的foreach
操作过程中引用数组变量。
Use Iterators
or don't rely on getting a consistent value from referencing the array variable during a foreach
operation.
这篇关于在foreach循环电流()的意外行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!