什么是cow(copy on write)?
这是PHP一种内存优化的手段,可以节省内存空间的浪费,我们可以看看下面的例子。
<?php
$a = range(0,20);
var_dump(memory_get_usage());
$b = $a;
var_dump(memory_get_usage());
$b = range(0,20);
var_dump(memory_get_usage());
输出结果是:
我们可以看到,实际上执行$b = $a 这一句时,内存使用量并没有增加。只有改变b或者a的值时才会真正的复制一遍内存。如果这里你使用的是简单的字符串变量赋值,可能打印的内存使用量是一样的,这是因为当我们调用emalloc申请内存的时候, PHP并不是简单的向OS要内存, 而是会像OS要一个大块的内存, 然后把其中的一块分配给申请者, 这样当再有逻辑来申请内存的时候, 就不再需要向OS申请内存了, 避免了频繁的系统调用.(详细可以见鸟哥文章-深入理解PHP内存管理之谁动了我的内存: http://www.laruence.com/2011/03/04/1894.html),所以这里我采用的随机数组。
如果用图解释的话大致是这样的:
如果这里是$b = &a的话,就属于引用传递,指向的地址是相同的,就好比一个人有两个名字,例如鲁迅和周树人,如果鲁迅被抓了,说明周树人也被抓了,作用的实体是一样的,这里我就不画图说明了。
什么是zval?
它是PHP的一种容器,从PHP7开始, 对于在zval的value字段中能保存下的值, 就不再对他们进行引用计数了, 而是在拷贝的时候直接赋值, 这样就省掉了大量的引用计数相关的操作, 这部分类型有:
IS_LONG
IS_DOUBLE
当然对于那种根本没有值, 只有类型的类型, 也不需要引用计数了:
IS_NULL
IS_FALSE
IS_TRUE,例如123属于is_long,不进行引用计数所以为0,
举个栗子,看下列代码(在php7中安装了xdebug扩展才可执行):
<?php
$a = 'mclink';
xdebug_debug_zval('a');
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
$b = 'good';
xdebug_debug_zval('b');
其中refcount是引用计数,is_ref为是否使用了引用,因为短字符串也算是IS_LONG类型的,所以第一个的refcount为0,is_ref也为0,然后b引用了a,所以a的refcount为2,这个东西不止它一个人用,还有另一个人。is_ref=1 说明所指向空间被引用了。
这里要注意的是:unset一个引用变量并不会释放其空间,只是取消了其引用。例如上例代码,如果我们unset($b),那么$a还是有值的,
对象的传递实际上就是一种引用传递
举栗子:
<?php
$a = 'mclink';
xdebug_debug_zval('a');
$b = &$a;
xdebug_debug_zval('a');
xdebug_debug_zval('b');
$b = 'good';
xdebug_debug_zval('b');
有关对象的引用,浅复制可以看我的另一篇文章说明:https://blog.csdn.net/qq_38378384/article/details/79850607