Bab*_*aba 39 php arrays foreach loops
这是一个简单的循环
$list = array("A", "B", "C","D");
foreach ($list as $var) {
print(current($list));
}
Run Code Online (Sandbox Code Playgroud)
输出(演示)
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
Run Code Online (Sandbox Code Playgroud)
题 :
foreach
我制作的,AAAA
但是在当前的PHP
稳定版本中没有得到它注意*我知道我可以简单地使用print $var
来自PHP DOC
current - 返回数组中的当前元素current()函数只返回内部指针当前指向的数组元素的值.它不会以任何方式移动指针.如果内部指针指向超出元素列表末尾或数组为空,则current()返回FALSE.
更新1 - 新观察
感谢Daniel Figueroa:只需通过包装current
功能,您就可以得到不同的结果
foreach ( $list as $var ) {
print(item($list));
}
function item($list) {
return current($list);
}
Run Code Online (Sandbox Code Playgroud)
输出(演示)
BCDA // What the hell
Run Code Online (Sandbox Code Playgroud)
题 :
foreach
输出?更新2
$list = array("A","B","C","D");
item2($list);
function item2($list) {
foreach ( $list as $var ) {
print(current($list));
}
}
Run Code Online (Sandbox Code Playgroud)
输出(见演示)
AAAA // No longer BBBB when using a function
Run Code Online (Sandbox Code Playgroud)
题 :
AAAA
外部和BBBB
函数Ja͢*_*͢ck 18
为什么从B开始?
因为5.2 foreach
(可靠地)在循环体开始之前使数组指针前进.另请参阅FE_RESET
操作码.
$list = array("A", "B", "C","D");
foreach ($list as $var) {
break;
}
var_dump(current($list));
Run Code Online (Sandbox Code Playgroud)
输出:
B
Run Code Online (Sandbox Code Playgroud)
这可能与ZEND_OP_DATA
伪操作码的工作原理有关(实际上没有记录).
为什么current()
继续给出相同的价值?
在循环开始之前,foreach
创建对您循环的数组的内部引用.一旦进入循环,每当修改或通过引用传递数组变量时,通过复制数组结构(但不是元素)将内部引用与变量取消关联.此复制的值保留数组指针(之前已由循环初始化修改).
这种行为也表现为更具破坏性的unset()
操作:
$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";
Run Code Online (Sandbox Code Playgroud)
输出:
ABCD
Array
(
[0] => A
)
Run Code Online (Sandbox Code Playgroud)
将循环变量传递给函数
这是另一个有趣的场景:
$list = array('A', 'B', 'C', 'D');
function itm($arr)
{
return current($arr);
}
foreach ($list as $item) {
print itm($list);
}
var_dump(current($list));
Run Code Online (Sandbox Code Playgroud)
输出:
BCDA
bool(false)
Run Code Online (Sandbox Code Playgroud)
这次,数组按值传递,因此其数组结构被复制(而不是元素)到函数的$arr
参数中.与前面的示例不同,循环的内部引用和$list
符号之间没有解除关联,因为复制发生在函数作用域中.
最后一个"A"
怎么样?
这是目前最神秘的行为,foreach
只能在这种情况下见证.在最后一个循环迭代中,数组指针似乎重绕到第一个项目; 看起来因为在循环结束时它显然超出了元素的末尾(正如你可以从输出的最后一行看到的).
这可能与在SWITCH_FREE
a结束时执行的操作码有关foreach
.
那么为什么放置foreach
一个函数会让它与众不同呢?
请注意以下代码:
function item2($arr)
{
foreach ($arr as $var) {
print(current($arr));
}
var_dump(current($arr));
}
$list = array("A","B","C","D");
item2($list);
Run Code Online (Sandbox Code Playgroud)
输出:
AAAA
string(1) "A"
Run Code Online (Sandbox Code Playgroud)
在这种情况下,foreach
使用数组的副本初始化该内部引用(因为它具有refcount> 1),因此会立即与$arr
符号解除关联.
会变得更糟吗?
当然!当您开始使用引用或foreach
在同一变量上嵌套多个循环时,您甚至可以获得更糟糕的结果.
那么我怎样才能获得一致的结果呢?
Iterators
在foreach
操作期间使用或不依赖于从引用数组变量获取一致值.