目录
- 一、环境
- 二、前言
- 三、字符串类型
- 四、数组类型
- 问题1:不变数组的作用是什么?
- 问题2:为什么非空的不变数组的refcount初始值是2?
 
- 五、引用类型
- 六、参阅
一、环境
PHP 7.4
二、前言
PHP的变量在底层有一个引用计数(refcount)属性,这个引用计数是为垃圾回收(GC)服务的,当引用计数变为0的时候,就代表这个变量可以被回收。
但也不是所有的数据类型都支持引用计数,例如一些简单类型如整型、浮点型、布尔型、NULL等,它们就不支持(表现为 refcount 的值恒为0)。不支持 refcount 的数据类型,不会被GC回收,它们在请求结束时才会释放。
可以使用xdebug_debug_zval函数查看变量的refcount(需要安装xdebug扩展):
// 整型
$a = 1;
xdebug_debug_zval('a'); // a: (refcount=0, is_ref=0)// 浮点型
$a = 1.1;
xdebug_debug_zval('a'); // a: (refcount=0, is_ref=0)// 布尔型
$a = true;
xdebug_debug_zval('a'); // a: (refcount=0, is_ref=0)// 空值
$a = null;
xdebug_debug_zval('a'); // a: (refcount=0, is_ref=0)
类型与引用计数:
| 名称 | 类型 | 引用计数 | 备注 | 
|---|---|---|---|
| 长整型 | Long | 不支持 | |
| 浮点型 | Double | 不支持 | |
| 布尔型 | Bool | 不支持 | |
| 空值 | NULL | 不支持 | |
| 字符串 | String | 看条件 | 当字符串是内部字符串(Interned String)时,不支持 | 
| 数组 | Array | 支持 | 当数组是不变数组(Immutable Array)时,refcount的初始值是2,而不是1,所以不变数组的 refcount 不会变为0,即不会被GC回收 | 
| 引用 | Reference | 支持 | |
| 资源 | Resource | 支持 | |
| 对象 | Object | 支持 | 
三、字符串类型
字符串类型分为“内部字符串”和“非内部字符串”。内部字符串不支持refcount,非内部字符串支持refcount,并且两者可以互相转换。
内部字符串就是内容不变的的字符串,例如通过字面量赋值的字符串变量就属于内部字符串:
// 例子1
$a = 'helloworld';
xdebug_debug_zval('a'); // a: (interned, is_ref=0)