当我们使用foreach时,内部究竟发生了什么(PHP5)?

WBOY
Release: 2016-06-23 13:08:13
Original
893 people have browsed it

以下所有结论均基于PHP5版本

看下面一段最基础的foreach遍历数组代码。

<?php $arr = array(‘a’,’b’,’c’);foreach ($arr as $key=> $value) {    echo $key,$value,’<br/>’; //output :  0a1b2c}?> 
Copy after login

输出为’0a1b2c’自然没有疑问,那么此过程中$arr,$key,$value究竟是经过怎样的运算,才输出这个结果的呢?

其实foreach遍历过程中,并不是直接操作$arr(原数组)的,而是会将$arr复制出一个$arrcopy(是一个$arr的一个复制品,我这里以$arrcopy代替),foreach在遍历过程中操作的其实一直是$arrcopy。

注:关于$arrcopy这个值我们是没办法提取出来的,因为这是我给他的命名,并没有存在这个变量,但是foreach遍历过程中确实会产生这么一个副本,这儿为了方便讲述我用$arrCopy代表。

Foreach遍历大概的流程是这样(伪代码):

<?php //伪代码$arr = array('a','b','c');/* foreach循环开始*///first loop$arrCopy = $arr; //复制出一个待循环数组的副本,接下来都是操作这个副本$key = currentKey($arrCopy); //将获取到的值分配给$k;$val = currentVal($arrCopy); //将获取到的值分配给$v;next($arrCopy);//移动副本数组的指针$arr = $arrCopy;//将副本赋值回给$arr((主要是将指针同步移动))//大括号内容{    echo $key,$value,’<br/>’;}//firt loop end//second loop $key = currentKey($arrCopy); //将获取到的值分配给$k;$val = currentVal($arrCopy); //将获取到的值分配给$v;………//seconde loop end?>
Copy after login

这就是foreach代码的运行流程,总结一句话就是foreach遍历操作的时候并不是原始数组,而是一个拷贝数组,但是每次循环的结尾都会将副本重新赋值回给原数组$arr = $arrCopy;。

如何证明我的说法呢?可以用下面这段代码检验。

<?php // $a = array('a','b','c'); $arr = array('a','b','c');foreach ($arr as $key=> $value) {    $arr[] = 'd';    print_r($arr);    var_dump($key,$value);}?>
Copy after login

输出结果为:

//output:Array    (    [0] => a    [1] => b    [2] => c    [3] => d    )    int(0)    string(1) "a"    Array    (    [0] => a    [1] => b    [2] => c    [3] => d    [4] => d    )    int(1)    string(1) "b"    Array    (    [0] => a    [1] => b    [2] => c    [3] => d    [4] => d    [5] => d    )    int(2)    string(1) "c"
Copy after login

同学们看出来了吗?

$arr数组的键值对一直在在增加,可是$key,$value的值到了int(2),string(1) “c”就结束了,并没有如我们所料的将值为d的那些键值对打印出来。

这儿就能证明,foreach遍历过程操作的是$arr的副本($arrcopy)。

对了,foreach使用过程中还有一些小地方需要注意。例如foreach遍历数组的指针问题:

 <?php $arr = array('a','b','c');var_dump(current($arr)); //output:string(1) "a"foreach ($arr as $key=> $value) {}var_dump(current($arr)); //output:bool(false)?>
Copy after login

两次输出,不一样的结果。为什么呢?因为foreach循环遍历后的数组,该数组的指针是指向末尾的(此处的话指针就是在’c’的右边),并且使用完毕后不会帮我们复位,所以我们var_dump(current($arr))为 bool(false)。那么在这里我们需要特别注意,为了保险起见我们在foreach遍历数组后,最好手动reset()一下数组,防止出错:

<?php $arr = array('a','b','c');var_dump(current($arr)); //output:string(1) "a"foreach ($arr as $key=> $value) {}reset($arr);var_dump(current($arr)); / output:string(1) "a"?>
Copy after login

这样就正常了。

还有一点PHP手册也提醒我们了:

转成代码的意思就是:

<?php $arr = array('a','b','c');foreach ($arr as $key=> $value) {}var_dump($key);var_dump($value);?>
Copy after login

Foreach遍历后,$key和$value是真实存在的,最好使用后能手动unset()掉。

总结:foreach算是PHP里面比较复杂的一个函数了,因为牵扯到PHP底层的C语言的结构体,引用(is_ref__gc),指针移动……,所以在使用foreach的时候一定要特别注意啊!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!