php中foreach使用引用的陷阱

有时候我们为了在循环过程中改变数组项的值,在foreach的时候变量入口可以加个&符合,

表示,循环过程中使用数组中原来的值,而不是一个复制的值,如

foreach ($array as &$item) {}

  

这样一来,我们在循环中修改$item的值的时候,实际上修改的是$array中对应的值,

而如果不加&符号的话,在循环中修改$item的值不会影响到$array。

例子:

$array = [
    ‘name‘ => ‘Jobs‘,
    ‘age‘  => 50,
];

foreach ($array as $key => $value) {
    $value = 22;
}
print_r($array);

foreach ($array as $key => &$value) {
    $value = 22;
}
print_r($array);

  

Array
(
    [name] => Jobs
    [age] => 50
)
Array
(
    [name] => 22
    [age] => 22
)

陷阱:两次循环使用同样的临时变量的情况下,如果第一次循环使用的是引用,

那么在第二次循环中即使没有加&符号,临时变量也是引用。

这个引用指向了数组中最后一个元素(循环到了最后一个元素结束)。

例子:

$array = [
    ‘name‘ => ‘php‘,
    ‘age‘ => 123,
];

foreach ($array as $key => &$value) {
    echo "key=$key, value=$value" . PHP_EOL;
}

foreach ($array as $key => $value) {
    echo "key=$key, value=$value" . PHP_EOL;
}

  

key=name, value=php
key=age, value=123
key=name, value=php
key=age, value=php

  

上面最后一行的value是"php",并不是我们期望的123,这是因为,在第二个foreach循环中,

每一次循环的时候,都修改了$array中的key为‘age‘的值,

第一次循环的时候,数组中的age就已经是php(第一个值)了,在后续的循环中会依次改变数组中最后一个值,

到最后一次循环的时候,取得的值是prev($array),也就是php了。

如何避免这个问题?

1、在第二次循环之前,unset($value)

2、第二次foreach的时候使用不同名字的变量,如$item

另:查看一个变量是否是引用可以使用xdebug_debug_zval函数(需要有xdebug扩展)。

xdebug_debug_zval的结果形如:

value: (refcount=2, is_ref=1)=123

时间: 2024-11-05 13:32:57

php中foreach使用引用的陷阱的相关文章

php foreach使用引用的陷阱

最近工作中在foreach中使用引用的时候出现一个怪现象,使用2次foreach的时候数组值发生了改变,代码示例如下 1 <?php 2 $arr = array('1','2','3'); 3 foreach($arr as &$row){ 4 } 5 foreach($arr as $row){ 6 } 我的预期结果是1,2,3 但是实际结果输出1,2,2奇怪了,遍历数组难道还会改变数组的值么,猜测原因肯定出现在&row这个引用上.在第2个循环里打印$arrArray( [0]

PHP中的&amp;传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么?

PHP中的&传值引用的问题,在foreach循环的结果能帮解释下输出的结果原理是什么? 代码如下: <?php $arr = array('one','two','three'); foreach ($arr as &$value){ echo 'Value:'.$value.'<br />'; } foreach ($arr as $value){ echo 'Value:'.$value.'<br />'; } ?>输出结果: Value:one V

C++ string中的几个小陷阱,你掉进过吗?

C++开发的项目难免会用到STL的string,使用管理都比char数组(指针)方便的多,但在得心应手的使用过程中也要警惕几个小陷阱,避免我们项目出bug却迟迟找不到原因. 1.  结构体中的string赋值问题直接通过一个例子说明,下面的例子会输出什么: #include <iostream> #include <string> #include <stdlib.h> using namespace std; struct flowRecord { string ap

PHP和Java中foreach循环的用法区别

1.foreach语句介绍: ①PHP: foreach 语法结构提供了遍历数组的简单方式.foreach 仅能够应用于数组和对象,如果尝试应用于其他数据类型的变量,或者未初始化的变量将发出错误信息. ②Java: foreach语句是java5的新特征之一,在遍历数组.集合方面,foreach为开发人员提供了极大的方便.foreach语句是for语句的特殊简化版本,但是foreach语句并不能完全取代for语句,然而,任何的foreach语句都可以改写为for语句版本.foreach并不是一个

Java中forEach, 用来遍历数组

这里的for是Java中forEach, 用来遍历数组的.for(int i : d) 就是遍历int型数组d的 每一次访问数组d的时候读取的数据放入int型的i中.和for(int i=0;i<d.length();i++)是一样的,但是forEach的可用场合较多. public class e1 {public static void main(String[] args){ int[]d=new int[] {1,2,3,4,64,1234,3124,657,22}; System.ou

oc中设置手动引用和自动引用图解

1.把整个工程都设为手动引用 ----------------------------选中MRCAPP  再找到bulid settings------------------ ---------------------------------------在搜索框中输入arc---------------------------------------------------- 2.设置某个类手动引用 选中某个需要设置的类 然后双击     会跳出对话框  在里面输入:“-fno-abjc-ar

Android学习笔记_78_ Android开发中使用软引用和弱引用防止内存溢出

在<Effective Java 2nd Edition>中,第6条"消除过期的对象引用"提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象池.缓存中的过期对象都有可能引发内存泄露的问题.书中还提到可以用 WeakHashMap来作为缓存的容器可以有效解决这一问题.之前也确实遇到过类似问题,但是没有接触过"弱引用"相关的问题,于是查阅了一些资料. <Java 理论与实践: 用弱引用堵住内存泄漏>

转 浅谈C++中指针和引用的区别

浅谈C++中指针和引用的区别 浅谈C++中指针和引用的区别 指针和引用在C++中很常用,但是对于它们之间的区别很多初学者都不是太熟悉,下面来谈谈他们2者之间的区别和用法. 1.指针和引用的定义和性质区别: (1)指针:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元:而引用跟原来的变量实质上是同一个东西,只不过是原变量的一个别名而已.如: int a=1;int *p=&a; int a=1;int &b=a; 上面定义了一个整形变量和一个指针变量p,该指针变量指向a

Swift编程语言中的方法引用(基于2.2版本)

由于Apple官方的<The Swift Programming Guide>对Swift编程语言中的方法引用介绍得不多,所以这里将更深入.详细地介绍Swift中的方法引用. Swift与Objective-C不同,由于Objective-C的方法都属于“消息”,因此直接用selector的消息签名即可表示一条确定的消息作为方法引用.而Swift的方法更类似于C++.Java中的方法,也就是说比Objective-C更静态,因此它不具有如此般灵活性. 另外,在Swift编程语言中,方法引用与C