当 foreach 开始执行时,数组内部的指针会自动指向第一个单元。若是移动指针的结果超出了数组单元的末端,则退出循环。php
$array = [ 'name' => 'Jobs', 'age' => 50, ]; foreach ($array as $key => $value) { $value = 22; //赋值,可是没有影响到$array[$key]位置的值,除非加上 $array[$key] = $value; }
上面的foreach 对数组内的值没影响。有时候咱们为了在循环过程当中改变数组项的值,在foreach的时候变量入口能够加个&符号,表示,循环过程当中使用数组中原来的值,而不是一个复制的值,如数组
$array = [ 'name' => 'Jobs', 'age' => 50, ]; foreach ($array as $key => &$value) { //直接改变数组$array[$key]位置的值 $value = 22; }
结果输出对比:函数
Array ( [name] => Jobs [age] => 50 ) Array ( [name] => 22 [age] => 22 )
$key
和$value
都是临时变量,foreach的时候,把每一个数组单元的键分别赋值给$key
,把每一个数组单元的值分别赋给$value
,相等于$value=$arr[$key]
,$value=2
仅仅是改变了$value
的值(非&传递),并不会影响到$array[$key]
,天然也就不会影响到$array
。debug
而用第二种方法(引用)的时候,相等于$value=&$array[$key]
,$array[$key]
和$value
指向同一内存地址,$value=2
天然就改变了$array[$key]
的值,也就改变了$array
的值指针
循环时,
$key
和$value
都是临时变量,只是赋值方式不一样code
陷阱:两次循环使用一样的临时变量的状况下,若是第一次循环使用的是引用,那么在第二次循环中即便没有加&符号,临时变量也是引用。这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。
内存
如:string
array = [ 'name' => 'php', 'age' => 123, ]; //标记为循环1: foreach ($array as $key => &$value) { echo "key=$key, value=$value" . PHP_EOL; } //循环完后,最后一个元素 $value = &$array['age'], 这里$value 和 $array['age'] 是引用关系,都是指向的同一个空间。 var_dump($array); 输出结果以下: array(2) { ["name"]=> string(3) "php" ["age"]=> &int(123) } //标记为循环2: foreach ($array as $key => $value) { //第一次循环进来 $value=$array['name'],此时$value = 'php',因为咱们开始的引用中, $value 和 $array['age'] 创建了引用,因此这里改变了$value的值, 其实就改变了 $array['name']的值,因此 $array['name'] = 'php', //之后的每次循环处理都和上面第一次相同 //获得的结果:其实每次循环赋值给$value的值,都是给“标记为循环1”中的最后一个元素在赋值,也就是说数组中最后一个元素的值 = 数组中的倒数第2个元素的值 echo "key=$key, value=$value" . PHP_EOL; }
上面的 foreach循环中输出结果以下:变量
key=name, value=php key=age, value=123 key=name, value=php key=age, value=php
总结:两次循环使用一样的临时变量的状况下,若是第一次循环使用的是引用,那么在第二次循环中即便没有加&符号,临时变量也是引用。
这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。
,获得的最后数据结果就是数组中最后一个元素的值 = 数组中的倒数第2个元素的值 (也就是说,最后2个元素的值相同,且为到倒数第2个元素的处理值)。扩展
方法1:在第二次循环以前,unset($value)
方法2:第二次foreach的时候使用不一样名字的临时变量
另:查看一个变量是不是引用可使用xdebug_debug_zval函数(须要有xdebug扩展)。
xdebug_debug_zval的结果形如: value: (refcount=2, is_ref=1)=123