大家一起来分析一下下面这段代码:

<?php

$arr = array();
$arr["abc"] = array("sex" => 100, "age" => 18);
$arr["bcd"] = array("sex" => 200, "age" => 19);
$arr["cde"] = array("sex" => 250, "age" => 17);

$arr2 = array();
foreach ($arr as $name => $item) {
    $item2 = &$arr2[$name];
    $item2["sex"] = $item["sex"] + 300;
    $item2["age"] = $item["age"] + 2;
}

//unset($item2);
foreach ($arr2 as $name => $item2) {
    echo "name: $name, age: " . $item2['age'] . ", sex: " . $item2['sex'] . PHP_EOL;
}

echo "too little".PHP_EOL;

//unset($item2);
$item2 = array("age" => 30, "sex" => 1000);
print_r($item2);

echo "next step".PHP_EOL;

foreach ($arr2 as $name => $item) {
    echo "name: $name, age: " . $item['age'] . ", sex: " . $item['sex'] . PHP_EOL;
}

如果你觉得上面的代码的执行结果是

name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 19, sex: 550
too little
Array
(
    [age] => 30
    [sex] => 1000
)
next step
name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 19, sex: 550

或者是

name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 21, sex: 500
too little
Array
(
    [age] => 30
    [sex] => 1000
)
next step
name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 21, sex: 500

那么你就应该继续往下看了。因为上面两个结果都是错误的,真正的执行结果如下:

name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 21, sex: 500
too little
Array
(
    [age] => 30
    [sex] => 1000
)
next step
name: abc, age: 20, sex: 400
name: bcd, age: 21, sex: 500
name: cde, age: 30, sex: 1000

为什么会是这样一个结果呢?

因为在第一个引用赋值的foreach循环结束以后,$item2依然引用着$arr2数组的最后一个元素。而第二个foreach循环的时候,相当于把$arr2数组的元素依次赋值给$item2,也就相当于赋值给最后一个元素。也就是说,在第二个foreach遍历的过程中,$arr2数组的变化是这样的:

循环到第1个元素时的数组:[1, 2, 1]
循环到第2个元素时的数组:[1, 2, 2]
循环到第3个元素时的数组:[1, 2, 2]

而后的

$item2 = array("age" => 30, "sex" => 1000);

是为了告诉大家引用关系依然存在,并且,直接赋值也会导致引用的数据发生变化。(其实,第二个foreach循环时也是使用的直接赋值,只是有点不好观察出来)

那么,怎样才能将$item2与$arr2的最后一个元素的引用关系去掉呢?其实很简单,只要添加以下语句就可以了。也就是源代码中注释的地方。

unset($item2);

这也可以说是PHP的一个小坑,对于PHP新手来说,很容易犯这种错误而云里雾里,不知所措。希望这篇文章能帮到这样的新手。

posted @ 2019-09-19 15:11 草谷子 阅读(1097) 评论(0) 推荐(0) 编辑
摘要: 感谢阿里巴巴,搭建并公开了Maven仓库的国内镜像站。话外:使用Maven的官方仓库真的是太slow了! 在<Maven Root>/conf/settings.xml中的<mirrors></mirrors>标签中,加入以下代码,即可使用阿里的镜像站了。 阅读全文
posted @ 2018-03-21 19:55 草谷子 阅读(338) 评论(0) 推荐(0) 编辑
摘要: 对应Python版:加密文件之Python版Java版比Python版要快得多,两个版本不在一个量级上。在加密解密1G大文件时,Java版花费的时间是秒级,而Python版花费的时间是10分钟级。 阅读全文
posted @ 2017-12-25 22:38 草谷子 阅读(1977) 评论(0) 推荐(0) 编辑
摘要: centos7.3默认使用的防火墙应该是firewall,而不是iptables。而我们xxmj服务器使用的是iptables防火墙。所以,在配置防火墙之前,我们需要先关闭firewall,安装iptables。 查看firewall的安装和启动状态 查看firewall的安装和启动状态 下面关闭f 阅读全文
posted @ 2017-04-11 15:43 草谷子 阅读(13701) 评论(0) 推荐(0) 编辑
摘要: 高级C#信使 作者:Ilya Suzdalnitski 译自:http://wiki.unity3d.com/index.php/Advanced_CSharp_Messenger 描述 前言 MissingReferenceException的原因和解决方案 信使 用法 事件监听器 注册事件监听器 阅读全文
posted @ 2017-01-17 20:01 草谷子 阅读(655) 评论(0) 推荐(0) 编辑
摘要: 今天在工作中遇到这样一个问题:给定1个矩形,左下角的点point(x, y),长w,高h,要在这个矩形里随机出n个不同的点用来种怪。这个算法该怎么写呢?这对于我来说确实成为了一个问题。图示如下: 由于任务时间紧,做的又是Demo的原因,我不假思索的写出了下面这个算法: //从[from, to]区间 阅读全文
posted @ 2016-11-08 12:51 草谷子 阅读(1147) 评论(1) 推荐(1) 编辑
摘要: CPU 1. lscpu:显示cpu架构信息 总处理器核心数量=处理器数量*每个处理器的核心数量*每个核心支持的线程数量。即:CPU(s) = Socket(s) * Core(s) * Thread(s)。 我们看一下MAN中是如何描述的: 2. cat /proc/cpuinfo:查看CPU详细 阅读全文
posted @ 2016-11-02 21:40 草谷子 阅读(154882) 评论(0) 推荐(9) 编辑
摘要: CentOS 6.5MySQL 5.6.33HandlerSocket 1.1.2# Get packagesshell> wget http://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.33.tar.gzshell> wget -O hand 阅读全文
posted @ 2016-09-28 13:28 草谷子 阅读(1059) 评论(4) 推荐(1) 编辑
摘要: 巨页 为什么使用巨页? 当一个进程使用一些内存的时候,CPU就把那部分内存标记成已被该进程使用的。为了提高效率,CPU会按4K字节块(它在很多平台上是默认值)分配内存。这些块被称作页。这些页可以被交换到磁盘上,等等。 因为进程地址空间是虚拟的,CPU和操作系统就得记住哪一页属于哪个进程,存储在什么地 阅读全文
posted @ 2016-07-04 19:16 草谷子 阅读(2313) 评论(0) 推荐(0) 编辑
摘要: 很多人在用NodeJs的setTimeout(callback, delay[, arg][, ...])编写定时任务时,习惯上直接操作callback外部的对象object(闭包的特点)。这样做有一个隐患,就是当callback真正执行的时候,外部对象object可能已经被销毁了(比如执行了自定义 阅读全文
posted @ 2016-04-21 17:53 草谷子 阅读(2184) 评论(0) 推荐(0) 编辑
点击右上角即可分享
微信分享提示