问题

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

<?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. 自动化运维工具-Ansible基础

    目录 自动化运维工具-Ansible基础 什么是Ansible 同类型软件对比 Ansible的功能及优点 Ansible的架构 Ansible的执行流程 安装Ansible ansible配置文件 ...

  2. 使用 vs code 创建 Django 项目

    操作流程: 1.前期准备工作 2.vs code配置Python环境 3.新建 Django 项目 4.vs code 配置 Debug Django 环境 5.浏览器查看效果 1.前期准备工作 安装 ...

  3. Linuxautofs自动挂载服务

    autofs服务程序是一种Linux系统守护进程,当检测到用户试图访问一个尚未挂载的文件系统时,将自动挂载该文件系统.将信息填入/etc/fstab文件后,系统在每次开机时都自动将其挂载,而autof ...

  4. kubernets过滤pod标签(labels)

    版权声明:本文为博主原创文章,支持原创,转载请附上原文出处链接和本声明. 本文地址:https://www.cnblogs.com/wannengachao/p/12074399.html 1.查看p ...

  5. 不依赖官方LibPack编译FreeCAD的一次尝试

    在Windows下编译FreeCAD,通常的方法是依赖官方提供的LibPack,但是只有vs2008, vs2012, vs2013等几个版本提供.比如现在感觉vs2017比较好用,可是没有官方Lib ...

  6. python通过重启线程,实现服务的热加载

    这个思路后来证明不能用于工作. 因为线程调用没有及时返回,所以不能用这种方式来重启服务. 但作为脑洞,也应该作个记录. import os import shutil import datetime ...

  7. echarts常用说明

    import { Injectable } from '@angular/core'; //模板option通用 let fff7 = '#fff'; //字体统一颜色rgba(255,255,255 ...

  8. os 和 sys 的模块使用方法和模块

    os  的模块  方法 os.remove()删除文件 os.rename()重命名文件 os.walk()生成目录树下的所有文件名 os.chdir()改变目录 os.mkdir/maked ...

  9. 给Java0基础的五个学习的思路?

    关于Java初学者来说,想学习Java教程,需求了解,根底打好才干学得更好,Java教程之学习Java的路线图的五个必经阶段,希望能对Java学习者有所帮忙. 第一个阶段-java根底阶段 1.jav ...

  10. LinqMethod 实现 LeftJoin

    LinqMethod 实现 LeftJoin Intro 有时候我们想实现 leftJoin 但是 Linq 提供的 Join 相当于是 INNER JOIN,于是就打算实现一个 LeftJoin 的 ...