深入解析PHP的引用计数机制


Posted in PHP onJune 14, 2013

PHP的变量声明并赋值后,变量名存在符号表中,而值和类信息存在zval中,zval中包含四个变量,is_ref,refcount,value,type,zval源码如下

struct _zval_struct {  
    /* Variable information */  
    zvalue_value value;     /* value */  
    zend_uint refcount__gc;  
    zend_uchar type;    /* active type */  
    zend_uchar is_ref__gc;  
};

refcount表示value地址与其相同的zval共有多少个,refcount=0时,zval被销毁
is_ref表示一个zval是否被引用,有“0”和“1”两种状态

此处分析一下什么时候zval会被复制或者开辟新的内存空间呢
1.当is_ref=0,且refcount>1时,如果改变某个指向该zval的变量的值,会生成新zval,原zval的refcount--,例如:$a=1;$b=$a;$b=2;,zval将被复制,也就是说原先ab指向同一个zval,后来b会使用新开辟的zval

2.当is_ref=0,且refcount>1时,如果将zval赋值给某个引用变量,那么用来赋值和变量和被赋值的变量会使用同一个原zval,而其他指向原zval的变量将会指向一个新复制的zval,且refcount会被重新计算,例如:$a=1;$b=$a;$c=$a;$d=&$a;,此时ad使用原zval,bc使用新复制出来的zval

3.当is_ref=1,且refcount>1时,如果将zval复制给某个非引用变量,该非引用变量会使用一个新复制的zval,元zval的refcount不变,例如:$a=1;$b=&$a;$c=$a,那么ab使用原zval,而c使用新复制的zval
type表示该zval的值类型,宏定义如下

#define IS_NULL     0  
#define IS_LONG     1  
#define IS_DOUBLE   2  
#define IS_BOOL     3  
#define IS_ARRAY    4  
#define IS_OBJECT   5  
#define IS_STRING   6  
#define IS_RESOURCE 7  
#define IS_CONSTANT 8  
#define IS_CONSTANT_ARRAY   9

value表示该zval的值,他也是个共同体,代码如下
typedef union _zvalue_value {  
    long lval;                  /* long value */  
    double dval;                /* double value */  
    struct {  
        char *val;  
        int len;  
    } str;  
    HashTable *ht;              /* hash table value */  
    zend_object_value obj;  
} zvalue_value;

现在你知道php是如何类型变换的了,因为他的值存的其实是个可以代表任何类型的结构体,而具体的取值则根据type来决定是用共同体里的哪个变量来存值的

见下面的例子1

.-----------
$a = 1;
$b = $a;
$c = $a;
.-----------
$d = &$a;
.-----------
$a = 2;
.-----------
$b = null;

查看refcount,is_ref,zval的变化
执行完第一部分后来看看输出
1-----------------------------
a:(refcount=3, is_ref=0),int 1
b:(refcount=3, is_ref=0),int 1
c:(refcount=3, is_ref=0),int 1
可以看出来a,b,c使用同一个zval
再看执行完第二部分的
2----------------------------
a:(refcount=2, is_ref=1),int 1
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 1
注意此时a,d在一起了,他们使用同一个zval,而bc使用一个新生成的zval,同时重新计算两个zval的refcount和is_ref
3----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=2, is_ref=0),int 1
c:(refcount=2, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
可以知道ad这两个is_ref=1的好基友的值是同时改变的
4----------------------------
a:(refcount=2, is_ref=1),int 2
b:(refcount=1, is_ref=0),null
c:(refcount=1, is_ref=0),int 1
d:(refcount=2, is_ref=1),int 2
bc由于他们的zval的is_ref=0,所以他们不是好基友,他们的值不会同时改变,于是bc的zval再次分裂,b = null c = 1
PHP 相关文章推荐
joomla内置的表单验证功能使用方法
Jun 11 PHP
php设计模式 Composite (组合模式)
Jun 26 PHP
joomla jce editor 解决上传中文名文件失败问题
Jun 09 PHP
php5.5新数组函数array_column使用
Jul 08 PHP
php下拉选项的批量操作的实现代码
Oct 14 PHP
php购物车实现方法
Jan 03 PHP
php进行ip地址掩码运算处理的方法
Jul 11 PHP
PHP使用mysqli操作MySQL数据库的简单方法
Feb 04 PHP
PHP中empty,isset,is_null用法和区别
Feb 19 PHP
PHPExcel 修改已存在Excel的方法
May 03 PHP
PHP信号处理机制的操作代码讲解
Apr 19 PHP
php TP5框架生成二维码链接
Apr 01 PHP
深入解析PHP垃圾回收机制对内存泄露的处理
Jun 14 #PHP
Mysql的Root密码忘记,查看或修改的解决方法(图文介绍)
Jun 14 #PHP
解析php中两种缩放图片的函数,为图片添加水印
Jun 14 #PHP
PHP操作Memcache实例介绍
Jun 14 #PHP
解析PHP处理换行符的问题 \r\n
Jun 13 #PHP
基于PHP5魔术常量与魔术方法的详解
Jun 13 #PHP
基于PHPExcel的常用方法总结
Jun 13 #PHP
You might like
php实现批量下载百度云盘文件例子分享
2014/04/10 PHP
ThinkPHP中的三大自动简介
2014/08/22 PHP
PHP创建word文档的方法(平台无关)
2016/03/29 PHP
浏览器窗口加载和大小改变事件示例
2014/02/27 Javascript
flash+jQuery实现可关闭及重复播放的压顶广告
2015/04/15 Javascript
JavaScript动态改变div属性的实现方法
2015/07/22 Javascript
谈谈我对JavaScript原型和闭包系列理解(随手笔记9)
2015/12/24 Javascript
基于JavaScript代码实现随机漂浮图片广告
2016/01/05 Javascript
浅谈JavaScript 中有关时间对象的方法
2016/08/15 Javascript
jQuery的Read()方法代替原生JS详解
2016/11/08 Javascript
浅析如何利用angular结合translate为项目实现国际化
2016/12/08 Javascript
vue音乐播放器插件vue-aplayer的配置及其使用实例详解
2017/07/10 Javascript
Node.js如何优雅的封装一个实用函数的npm包的方法
2019/04/29 Javascript
Flutter实现仿微信底部菜单栏功能
2019/09/18 Javascript
vue 实现移动端键盘搜索事件监听
2019/11/06 Javascript
浅谈nuxtjs校验登录中间件和混入(mixin)
2020/11/06 Javascript
js面向对象方式实现拖拽效果
2021/03/03 Javascript
详解Python字符串对象的实现
2015/12/24 Python
Python读取图片属性信息的实现方法
2016/09/11 Python
python3调用R的示例代码
2018/02/23 Python
python logging日志模块以及多进程日志详解
2018/04/18 Python
python中多个装饰器的执行顺序详解
2018/10/08 Python
对Python 获取类的成员变量及临时变量的方法详解
2019/01/22 Python
HTML5中判断用户是否正在浏览页面的方法
2014/05/03 HTML / CSS
Tech21美国/加拿大:英国NO.1防摔保护壳品牌
2018/01/20 全球购物
毕业生的自我鉴定该怎么写
2013/12/02 职场文书
优秀德育工作者事迹材料
2014/05/07 职场文书
医学专业自荐信
2014/06/14 职场文书
单位租房协议书样本
2014/10/30 职场文书
党的群众路线教育实践活动个人对照检查材料(教师)
2014/11/04 职场文书
感谢信怎么写
2015/01/21 职场文书
小学新教师个人总结
2015/02/05 职场文书
老人与海读书笔记
2015/06/26 职场文书
党员学习型组织心得体会
2019/06/21 职场文书
background-position百分比原理详解
2021/05/08 HTML / CSS
使用这 6个Vue加载动画库来减少我们网站的跳出率
2021/05/18 Vue.js