问题

为了引出问题, 先来看下面一段代码:

<?php
$arr = [
'a', 'b',
'c', 'd',
]; foreach ($arr as &$each){
echo $each;
}
echo PHP_EOL;
foreach ($arr as $each){
echo $each;
}

这段代码很简单, 输出数组的元素两次, 感觉会输出两次 abcd? 不好意思, 输出结果如下: 

是不是感觉很奇怪?我没有给数组赋值啊,数组的最后一个元素怎么在第二次循环的时候改变了呢?

问题分析

再来看下面一段修改过得代码:

<?php
$arr = [
'a', 'b',
'c', 'd',
]; foreach ($arr as &$each){
echo $each;
}
echo PHP_EOL;
$each = '1';
var_dump($arr);

是不是发现了什么?

修改each变量会修改arr的最后一个元素, 这是为什么呢?

有过C语言使用经验的大概一看就明白是怎么回事了.

仔细看上面的foreach循环, each变量使用了&符号, 这个符号相当与c中的取址

php的foreach会在每次循环时,讲当前元素赋值给each, 然后进入循环体

当foreach遍历完成后, each变量没有释放而是指向了arr数组中的最后一个元素, 所以在后面给each赋值时, 其实改变的时arr数组的最后一个元素

到此, 流程已经明白了, 下面还原一下最开始的两次foreach过程:


在第一个foreach完成之后, 显然, each是指向数组的最后一个元素的, 下面进入第二个foreach:

  • 第一次遍历, 将arr[0]赋值给each, 相当于arr[3]=arr[0], 此时arr为: ['a', 'b', 'c', 'a']

  • 第二次遍历, 将arr[1]赋值给each, 相当于arr[3]=arr[1], 此时arr为: ['a', 'b', 'c', 'b']

  • 第三次遍历, 将arr[2]赋值给each, 相当于arr[3]=arr[2], 此时arr为: ['a', 'b', 'c', 'c']

  • 第四次遍历, 将arr[3]赋值给each, 相当于arr[3]=arr[3], 此时arr为: ['a', 'b', 'c', 'c']

分析的结果与之前输出的结果相同, 我们将第二次foreach的每次变化打印出来, 代码如下:

<?php
$arr = [
'a', 'b',
'c', 'd',
]; foreach ($arr as &$each){
}
foreach ($arr as $each){
var_dump($arr);
}

结果截图如下:

结果与我们分析的完全一致, 至此, 完结

我使用的php版本为: 7.2

PHP 循环引用的问题的更多相关文章

  1. block为什么用copy以及如何解决循环引用

    在完成项目期间,不可避免的会使用到block,因为block有着比delegate和notification可读性更高,而且看起来代码也会很简洁.于是在目前的项目中大量的使用block. 之前给大家介 ...

  2. ios 避免循环引用

    类似网络请求的情况下会导致循环引用,但是 如果网络请求的对象是局部变量,就必须用self,不能用weakSelf,否则,一旦当前方法所在对象销毁,那weakSelf就为空了(如果目的是这样,那就另当别 ...

  3. webapi修改tt模板给字段添加JsonIgnore特性解决转换json循环引用问题

    0.问题描述 EF生成的model带有导航属性,则json序列化会报循环引用错误,尝试如下 protected void Application_Start() { GlobalConfigurati ...

  4. 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用

    学习 EF Code First+MVC 时遇到了在请求JsonResult时出现 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用 的异常,原因 ...

  5. 关于json序列化循环引用导致出错

    以下是错误信息: Caused by: java.lang.IllegalStateException: circular reference error  Offending field: meth ...

  6. iOS之weak和strong、懒加载及循环引用

    一.weak和strong 1.理解 刚开始学UI的时候,对于weak和strong的描述看得最多的就是“由ARC引入,weak相当于OC中的assign,但是weak用于修饰对象,但是他们都不会造成 ...

  7. 第3月第9天 循环引用 block

    一.一个对象没有被引用,那么在函数块完成时就会被dealloc,这种情况因为对象销毁了,block块也永远不会执行. MyNetworkOperation *op = [[MyNetworkOpera ...

  8. spring jpa 实体互相引用返回restful数据循环引用报错的问题

    spring jpa 实体互相引用返回restful数据循环引用报错的问题 Java实体里两个对象有关联关系,互相引用,比如,在一对多的关联关系里 Problem对象,引用了标签列表ProblemLa ...

  9. 【转】iOS学习之容易造成循环引用的三种场景

    ARC已经出来很久了,自动释放内存的确很方便,但是并非绝对安全绝对不会产生内存泄露.导致iOS对象无法按预期释放的一个无形杀手是——循环引用.循环引用可以简单理解为A引用了B,而B又引用了A,双方都同 ...

  10. iOS 循环引用

    1.循环引用一般是指:A持有B,B同时持有A,从而导致死循环无法释放对象. 2.一般循环引用出现在block和delegate中,而一般解决方法就是将self变成weakSelf(强引用变成弱引用), ...

随机推荐

  1. linux学习(十)Shell中的控制语句

    目录 1. 条件测试语句 1.1 test语句 1.2[]语句 1.3文件测试 1.4字符串测试 1.5数值测试 1.5逻辑操作符 @(Shell中的控制语句) 1. 条件测试语句 测试语句十Shel ...

  2. MSSQL注入:显错注入及反弹注入

    前言: MSSQL注入攻击是最为复杂的数据库攻击技术,由于该数据库功能十分强大,存储过程以及函数语句十分丰富,这些灵活的语句造就了新颖独特的攻击思路. MSSQL的显错注入操作: 以联合查询为例: 猜 ...

  3. Linux—chattr 命令详解

    chattr命令的用法:chattr [ -RV ] [ -v version ] [ mode ] files…最关键的是[mode]部分,[mode]部分是由+-=和[ASacDdIijsTtu] ...

  4. Linux—vi/vim命令详解

    如何在 vi 里搜索关键字 在命令模式下敲斜杆( / )这时在状态栏(也就是屏幕左下脚)就出现了 "/" 然后输入你要查找的关键字敲回车就行了. 如果你要继续查找此关键字,敲字符 ...

  5. [PHP] 循环查看php-fpm的内存占用情况

    在webmail的业务中进行发信,如果携带了附件,会把附件拼接内嵌到邮件正文里,这时会极大的占用内存,可以使用以下命令查看fpm的进程内存占用 ps --no-headers --sort -rss ...

  6. gcc栈溢出保护机制:stack-protector

    关键词:stack-protector.stack-protector-strong.stack-protector-all等等. 1. gcc栈保护机制stack-protector简介 gcc提供 ...

  7. Acwing 14. 不修改数组找出重复的数字

    题目地址  https://www.acwing.com/problem/content/description/15/ 来源:剑指Offer 给定一个长度为 n+1n+1 的数组nums,数组中所有 ...

  8. mysql中group by 使用

    问题描述 我现在需要查询表test,里面需要安装字段a 进行分组.分组之后还有按照b字段最大的.还要查询出字段c. 我先在使用的数据库是mysql8.0 解决 需注意: group by 分组的时候是 ...

  9. python之爬取练习

    练习要求爬取http://yuedu.anyv.net/网址的最大页码数和文章标题和链接 网址页面截图: 代码截图: 完整代码: 根据网页显示页码的方式,爬取的所有页码中倒数第二个页码是最大页码. i ...

  10. 浅谈状态压缩DP

    浅谈状态压缩DP 本篇随笔简单讲解一下信息学奥林匹克竞赛中的状态压缩动态规划相关知识点.在算法竞赛中,状压\(DP\)是非常常见的动规类型.不仅如此,不仅是状压\(DP\),状压还是很多其他题目的处理 ...