继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

PHP强化之06 - 变量的引用机制

慕虎7371278
关注TA
已关注
手记 1250
粉丝 203
获赞 873

----- 最后更新【2018-12-6】-----
目录预览:
》一、概念
》二、变量的存储方式
》三、变量的引用机制
》四、从zval变量容器底层去了解引用
》五、unset与引用
》六、对象与引用
》七、测试题
》八、参考文献

一、概念

在PHP中引用意味着用不同的名字访问同一个变量内容。

定义方式:使用&符号

二、变量的存储方式

在讲解变量的引用之前,我们先来了解一下变量的存储方式。

下面以一个例子来说明:

// 1、定义一个变量$a$a = '111';   //当我们定义一个变量$a时,那么程序就会为它在内存当中开启一个内存空间,此时$a就指向这个内存空间(内存空间里存储着相应的值)。// 2、定义一个变量$b,然后将$a的值赋值给$b$b = $a;      //这时程序不会为变量$b再开启一个内存空间,这里涉及到了php的COW机制。//只有对$a或$b中的其中一个进行修改时,才会进行复制一份内存。//3、修改$a$a = '222';    //复制一份内存,用于存储修改后的值。

附:COW(copy on write)是内存优化的常见手段,在php中也采用了这种方式来优化内存。COW:写时复制,即只有当对其中一个或多个变量进行写操作的时候,才会复制一份内存,对其内容进行修改。

验证:
php有个函数memory_get_usage()可以用来查看PHP所使用的内存情况。

webp

验证内存变化

如上图可以看出,前面两个打印出来的内存使用情况相差并不大,而第三个则拉开了很大的差距,这是因为当修改变量$a时,程序为变量$a复制了一份内存用于存储修改后的值。

三、变量的引用机制

我们接着上面的例子,把$b = $a改为$b = &$a,结果分析如下:

webp

从上面可以看出,三个打印出来的内存使用情况差别都不大,这就是引用的机制。上面的情况无论你是修改$a还是$b,最后$a和$b都会变为修改后的值,程序并没有为修改后的变量开启新的内存空间。

四、从zval变量容器底层去了解引用

众所周知php的变量都是通过zend引擎来处理的,而zval结构体则是管理我们变量的一个容器,而xdebug_debug_zval函数则是我们调试zval结构体的一个好工具(注意,想使用该函数需要安装Xdebug插件)。

使用函数xdebug_debug_zval()打印出来的zval结构如下:

<?php$a = 'aaa';
xdebug_debug_zval('a');

在浏览器输出如下内容:

a:
(refcount=1, is_ref=0)string 'aaa' (length=3)

结构说明:
1)refcount表示引用计数,用来记录有多少个变量指向这个zval容器;
2)is_ref表示是否为引用,一个bool型的值;
3)表示数据的类型;
4)最后则为它的值。
注意:当refcount为1的时候,is_ref必须为0。当refcount为0的时候,该容器会被删除掉,释放空间出来。

webp

没有引用

webp

使用引用

五、unset与引用

当一个变量是使用了引用时,unset函数只会删除引用,并不会销毁内存空间。

由如下分析可以证明:

webp

从上面可以看出,三次打印出来的内存使用情况基本没有什么变动。

六、对象与引用

在PHP中,对象本身就是引用传递。

验证如下:

webp

分析:

1)当定义$a2 = $a1时,zval结构体的refcount值由1变为2;
2)此时无论修改的是$a2->type还是$a1->type的值,其实修改的都是同时一个空间里的值;
3)由此可以发现此时并没有使用到COW机制;
4)这是因为这种情况下$a1和$a2引用到了同一个对象。

七、测试题

1、写出如下程序的输出结果

$data = ['a', 'b', 'c'];foreach($data as $k => $v){
        $v = &$data[$k];
}//程序运行时,每一次循环结束后变量$data的值是什么?//程序执行完后,变量$data的值是什么?

运行结果如下:

webp



作者:Nosee123
链接:https://www.jianshu.com/p/f643bd68caa7


打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP