深入理解php的引用赋值

关于php引用的一般问题大家看资料就行了,这次我们来聊点有趣的东西。今天一个朋友在群里面问起来一个关于变量引用赋值的问题,问题本身很简单,我突然想做一个实验,来看看array直接赋值和引用赋值性能上的差别,写完代码发现另外一个问题.请看代码

<?php
$a = array_fill(0, 1000000, 10);

function test_time_cost($loop, $func) {
    $start = microtime(true);
    for($i = 0; $i < $loop; $i++) $func();
    $elapsed = (microtime(true) - $start) / $loop;
    echo "elapsed $elapsed\n";
};

function fetch_data($b) {}

test_time_cost(10000, function() {
    global $a; fetch_data(&$a);
});

test_time_cost(10000, function() {
    global $a; fetch_data($a);
});

代码在第二个测试函数里出错了,内存不够了。但是问题是php在变量赋值以后,如果目标变量未被使用,是不会执行赋值操作的。因为php语言在处理变量赋值时实际上是给$a和$b开辟了一个变量容器,在容器里$a和$b是对等的,可以简单理解为引用关系。但是当$b被改动时,$b就会被移出容器。

<?php

$a = array_fill(0, 1000000, 10);
$b = $a;      // 内存不增加
$b[0] = 10; // $a所占内存会赋值给$b

fetch_data函数实际上未对变量做任何处理,怎么会触发复制呢?于是我写了下面的代码


<?php

echo "memory_limit = " . ini_get('memory_limit') ."\n";

echo "memory init = " . memory_get_usage(true) . "\n";
$a = array_fill(0, 10000, 10);
echo "memory after a = " . memory_get_usage(true) ."\n";
$c = $b = $a;
echo "memory after c,b = " . memory_get_usage(true) ."\n";

function fetch_data($m) {
    echo "memory in fetch_data = " . memory_get_usage(true) ."\n";
}

fetch_data($a);

global $a; fetch_data($a);


运行结果如下


memory_limit = 128M
memory init = 786432
memory after a = 1835008
memory after c,b = 1835008
memory in fetch_data = 1835008
memory in fetch_data = 3670016

说明在声明global $a以后发生了变量拷贝赋值,既然是这样,看看php的文档吧,是不是对global申明的变量有什么特殊处理。看了一遍,没什么特殊的,就是创建引用对象。于是我又仔细看了一次php关于引用的说明,http://php.net/manual/en/features.gc.refcounting-basics.php. 我这次准备跟踪一下引用计数器

$a = array_fill(0, 1, 10);
$c = $b = $a;
echo "c,b,a\n";
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');

echo "changing b\n";
$b[0] = 8;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');

echo "global a\n";
global $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');

echo "c,b,global a\n";
$c = $b = $a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
xdebug_debug_zval('c');

运行的结果

c,b,a
a: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
b: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
c: (refcount=3, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
changing b
a: (refcount=2, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
b: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=8)
c: (refcount=2, is_ref=0)=array (0 => (refcount=1, is_ref=0)=10)
global a
a: (refcount=1, is_ref=1)=array (0 => (refcount=2, is_ref=0)=10)
b: (refcount=1, is_ref=0)=array (0 => (refcount=1, is_ref=0)=8)
c: (refcount=1, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)
c,b,global a
a: (refcount=1, is_ref=1)=array (0 => (refcount=2, is_ref=0)=10)
b: (refcount=2, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)
c: (refcount=2, is_ref=0)=array (0 => (refcount=2, is_ref=0)=10)

终于看出了问题,在没有global $a的时候,a,b,c在同一个变量容器里,所以没有发生复制行为。但是在声明global $a以后再进行复制,b,c不和a在同一容器了。我觉得原因就在于$a这个时候已经不是简单的变量了,可以理解为一个指针。php在这个时候没有办法创建变量容器同时给变量和指针,所以拷贝于是就发生了。

希望今天这个实验能加深大家对php引用的理解。我的微博 "James胡建",QQ号码 914244905,欢迎关注我。

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 、4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、下载 4使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合;、 4下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.m或d论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 、1资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资源 5来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。、资 5源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。 1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md或论文文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。 5、资源来自互联网采集,如有侵权,私聊博主删除。 6、可私信博主看论文后选择购买源代码。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值