PHP中的一个”坑“

  说一个极有可能在工作中遇到的问题——foreach的引用

$arr = range(1,3);
//[1,2,3]

foreach($arr as &$val) {
}

foreach($arr as $val) {
}
print_r($arr);
 

  上面这段代码输出什么呢,神奇的竟然是下面这样,这个我在工作中遇到过一次,当时弄了半天没弄出个所以然,只是找到了解决办法,这个问题解决办法有两个:

Array
(
    [0] => 1
    [1] => 2
    [2] => 2
)

  下面这两种方式都可以解决上面这个问题:

//方法1
foreach ($arr as &$value) {
}
unset($value);
foreach ($arr as $value) {
}
print_r($arr);
//[1,2,3]

//方法2
foreach ($arr as &$value) {
}
foreach ($arr as $val) {
}
print_r($arr);
//[1,2,3]
//方法3
foreach ($arr as &$value) {
}
foreach ($arr as &$value) {
}
print_r($arr);
//[1,2,3]

  方法1在官方的手册中也可以看到http://php.net/manual/en/control-structures.foreach.php,文章中专门有个tips提示这一点

  方法2和方法3为什么也ok呢,看了下面就知道了,其实就是引用在”作祟“,foreach中的&$value是一个指向数组中某一个元素的指针变量,先看下面个,这个很好理解,tmp是var的引用,指向的是var的存储空间,当tmp改变的时候,var也改变

$var = 123;
$tmp = &$var;
$tmp = 200;
echo $var;
//200

   看看下面这张盗来的图(哈哈,原文链接贴在下面),对上面这个更好的理解

  好了,这个ok了之后再看下面的(我不知道上面这种图用什么软件画的,只能手绘了,囧~~),先看第一个foreach:

第二次foreach:

  这个时候就很容易知道其实第二次foreach循环,数组中最后一个元素值真是多变啊~~,从第一个元素一直变到倒数第二个,要解决这个问题,很简单,切断$value与第二次foreach的关系,因此,unset可以,换个变量名也可以,或者将指针重置也可以(方法3),好了,至此,这个问题到这个地方基本可以理解个所以然了。

  好,再看看下面这个官方文档下面的评论,应该可以很容易理解了

<?php
$arr1 = array("a" => 1, "b" => 2, "c" => 3);
$arr2 = array("x" => 4, "y" => 5, "z" => 6);

foreach ($arr1 as $key => &$val) {}
foreach ($arr2 as $key => $val) {}

var_dump($arr1);
var_dump($arr2);
?>

The output is:
array(3) { ["a"]=> int(1) ["b"]=> int(2) ["c"]=> &int(6) }
array(3) { ["x"]=> int(4) ["y"]=> int(5) ["z"]=> int(6) }

参考文章:

  http://www.cnblogs.com/CraryPrimitiveMan/p/4030748.html#3085766

http://www.jb51.net/article/39299.htm

  本文版权归作者iforever([email protected])所有,未经作者本人同意禁止任何形式的转载,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利。

时间: 2024-10-06 06:30:46

PHP中的一个”坑“的相关文章

openlayer关于feature中的一个坑

在Openlayer中使用Feature时候,有时候我们需要使用图片来做Maker,今天就讲我在这碰到的一个坑. 这一个除了黄色部分其他部分透明的png图片. 将其加入地图中后. 我们要注册一个Feature的Select事件. 结果,点击中间透明部分时,竟然没有信息提示,只有点击黄色部分时候才有提示!这不科学!!! 后来,为了证明是不是图片中间透明的原因.我请美工妹妹帮我弄了另一张图. 就是它了.替换图片后,结果是点击圆里都行!这不科学啊! 好了,这是一个坑,写下来纪念. 有关于openlay

在Java中==的一个坑

观察下面代码,输出结果是什么? public static void main(String[] args) { Integer p = 10000; Integer q = 10000; System.out.println(p == q); System.out.println(p.equals(q)); } 运行一次,答案与预想的完全不一样.在比较数字的时候,一定要用euqals,不能用==c 查看Integer的jdk源码,发现如下片段: /** * Cache to support t

PHP中逻辑运算符and/or与||/&amp;&amp;的一个坑

我原来以为PHP中的and和&&是一样的, 只是写法上为了可读性和美观, 事实上我错了. 这里面深藏了一个坑! 看以下代码: $bA = true; $bB = false; $b1 = $bA and $bB; $b2 = $bA && $bB; var_dump($b1); // $b1 = true var_dump($b2); // $b2 = false $bA = false; $bB = true; $b3 = $bA or $bB; $b4 = $bA ||

使用ffmpeg视频编码过程中踩的一个坑

今天说说使用ffmpeg在写视频编码程序中踩的一个坑,这个坑让我花了好多时间,回头想想,很多时候一旦思维定势真的挺难突破的.下面是不正确的编码结果: 使用ffmpeg做视频编码过程中,首先要新建数据帧,并为数据帧分配相应内存,以便于保存图像数据,为数据帧分配内存需要用到av_image_alloc()这个函数,该函数将根据传入的图像宽.高.图像格式.数据对齐基数等参数进行内存分配. 这其中有一个参数可能会让人迷惑,那就是数据对齐基数这个参数该设置多少?顺便说说为什么要数据对齐,之所以要对齐,主要

CodeIgniter中使用CSRF TOKEN的一个坑

事情的经过是这样的,一个自动化扫描工具说我的代码中存在XSS漏洞,什么是XSS不懂的朋友可以看这里 我的代码里面开启CodeIgniter框架的CSRF Token,如下: 很简单,更多详情参考CI官方文档,主要用法就是在form_open时候自动插入一个隐藏的token值,当然还可以直接用php echo security->csrf_hash来配合其他一些用法,这里不多说. 接下来说说我的代码,Controller中代码如下: 视图层代码这里页写得比较简单: 代码中只是生成一个form里面带

记录我开发工作中遇到HTTP跨域和OPTION请求的一个坑

我通过这篇文章把今天工作中遇到的HTTP跨域和OPTION请求的一个坑记录下来. 场景是我需要在部署在域名a的Web应用里用JavaScript去消费一个部署在域名b的服务器上的服务.域名b上的服务也是我开发的,因此我将域名a加到了该服务的HTTP响应结构的头文件里,这样就允许了域名a上的JavaScript代码用AJAX访问域名b的服务. 域名b上的服务是一个Servlet,允许域名a跨域访问的代码就一行: protected void doGet(HttpServletRequest req

java中变量命名和引用变量的一个坑

这次有两个主题,第一个太简单啦,就是java中变量的命名规则,纯记忆性东西.第二个主题,就是讨论一下对象引用变量的一个注意点. 如果你对命名规则很熟啦,就直接看第二个内容吧.(上边的图稍微有点顺序紊乱啊) 一.java中变量的命名规则 大多数语言的命名规则是相似的,只有一些微小的差别. 变量的第一个位置,可以是字母,下划线(_),美元符($) (这个在c/c++,python中是不行的)(注意:不能是数字哦,一想就知道啦为什仫) 其他的位置可以是数字,字母,下划线 不能使用java中的关键字 j

说说PHP中foreach引用的一个坑

From: http://blog.csdn.net/yipiankongbai/article/details/45307767 先来看看下面这段代码: <?php $arr = array('apple','banana','cat','dog'); foreach($arr as $key=>$val) { //some code } echo $val; //输出dog echo $key; //输出3 //下面对val进行赋值 $val = 'e'; print_r($arr); /

bootstrap 中的静态模式的控制按钮上的一个坑

在使用modal时发现,代码:<button class="btn btn-danger" data-toggle="modal" data-target="#myModal">删除</button>,button按钮点击没有反映,经过与自带的实例对比,发现一个区别,就是type="button"没有加,真是一个坑啊 <button class="btn btn-danger"