PHP中each使用与数组变量分离的方法小结

WBOY
Freigeben: 2016-06-20 13:01:22
Original
840 Leute haben es durchsucht

在PHP开发中,遇到这个问题,将问题简化下,如下:

$arr = array(1,2,3,4,5,6);
$n = 3;

foreach($arr as $key=>$val){
    if($val == $n) break;
}
while(list($k,$v) = each($arr)){
    echo $v;
}
Nach dem Login kopieren

由于 each() 循环不会自动重置的数组指针,那么上边代码执行输出: 456

但是写在函数中结果却不同了,如下:

$arr = array(1,2,3,4,5,6);
$n = 3;
test1($arr,$n);
function test1($arr,$n) {


    foreach($arr as $key=>$val){
        if($val == $n) break;
    }
    while(list($k,$v) = each($arr)){
        echo $v;
    }
}
Nach dem Login kopieren

代码执行结果为: 123456

 

其实都是php的变量"写时复制(copy on write)"惹的祸,为什么这么说,且看分析:

什么是"写时复制(copy on write)"?

这里用一个例子说明:

$arr = array(1,2,3,4,5,6);
$n = 3;

$arr1 = $arr; // 此时并没有复制,是引用关系
debug_zval_dump($arr); // recount = 3,因为debug_zval_dump有一次
$arr[0] = 1; // 此时有写操作,要分离
debug_zval_dump($arr); // recount = 2
Nach dem Login kopieren


php手册上说:
因为将一个数组赋值给另一个数组时会重置原来的数组指针,因此在上边的例子中如果我们在循环内部将$fruit 赋给了另一个变量的话将会导致无限循环。
php手册关于each介绍有提到,其实就是说数组变量分离的时候会重置数组的指针,看下面的例子:

 

$arr = array(1,2,3,4,5,6);
$n = 3;

$arr1 = $arr; // 此时并没有复制,是引用关系,可以看作是函数复制调用

foreach($arr as $key=>$val){
    if($val == $n) break;
}

debug_zval_dump($arr); // refcount = 3
list($k,$v) = each($arr); // 因为each会改变数组的指针,所以还是写操作,存在分离
echo $v;
debug_zval_dump($arr); // refcount = 2
Nach dem Login kopieren

 

至于&操作的话,不存在“变量分离”,或者说“变量分离”是在&操作的同时完成的。

 

$arr = array(1,2,3,4,5,6);
$n = 3;

$arr1 = &$arr; // 引用,“变量分离”是在&操作的同时完成

foreach($arr as $key=>$val){
    if($val == $n) break;
}

debug_zval_dump($arr); // refcount = 2
list($k,$v) = each($arr); // 不存在变量分离
echo $v;
debug_zval_dump($arr); // refcount = 2
Nach dem Login kopieren


相同的效果还有:

$arr = array(1,2,3,4,5,6);
$n = 3;

$arr1 = $arr; // 此时并没有复制,是引用关系,可以看作是函数复制调用

foreach($arr as $key=> &$val){ // 存在可能写的情况,变量分离
    if($val == $n) break;
}

debug_zval_dump($arr); // refcount = 2
list($k,$v) = each($arr); // 不存在变量分离
echo $v;
debug_zval_dump($arr); // refcount = 2
Nach dem Login kopieren

所以在使用each之前,最好是先用reset(如果存在引用会产生变量分离)统一重置数组指针,就可以避免上述问题。


Verwandte Etiketten:
php
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage