🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
[TOC] * * * * * ### 一. 概念 * 即用不同的名字访问同一个变量内容; ### 二. 定义符号 * 使用 & 符号; ### 三. COW机制 写时复制(Copy-on-Write,也缩写为COW),顾名思义,就是在写入时才真正复制一份内存进行修改; ~~~ $a = range(0,1000); var_dump(memory_get_usage()); // 打印内存使用情况 $b = $a; var_dump(memory_get_usage()); // 此时 , $a 与 $b 指向同一个内存空间, 并不会因为$b的创建而开辟另一块内存空间 $a = range(0,1000); var_dump(memory_get_usage()); // 此时, $b还是指向最初的空间, 而$a会指向新的内存空间; ~~~ ### 四. PHP引用变量的原理 ~~~ $a = range(0,1000); var_dump(memory_get_usage()); $b = &$a; var_dump(memory_get_usage()); // 此时 , $a 与 $b 在一般情况下永远指向同一个内存空间, 并不会因为谁的更改而开辟另一块内存空间 $a = range(0,1000); var_dump(memory_get_usage()); // 此时, $a 与 $b 还是指向最初的空间; 改变的只是内存空间的值; ~~~ ### 五. xdebug_debug_zval()函数 的使用 * 每个php变量存在一个叫"zval"的变量容器中。 * 一个zval变量容器,除了包含变量的类型和值,还包括两个字节的额外信息。 * 一个是"is_ref",是个bool值,用来标识这个变量是否是属于引用集合(reference set)。 * 通过这个字节,php引擎才能把普通变量和引用变量区分开来。 * 由于php允许用户通过使用&来使用自定义引用,zval变量容器中还有一个内部引用计数机制,来优化内存使用。 * 另一个额外字节是"refcount",用以表示指向这个zval变量容器的变量(也称符号即symbol)个数。 ~~~ $a = 123; xdebug_debug_zval('a'); // a:(refcount=0, is_ref=0)int 123 $b = $a; xdebug_debug_zval('a'); // a:(refcount=0, is_ref=0)int 123 $c = &$a; xdebug_debug_zval('a'); // a:(refcount=2, is_ref=1)int 123 ~~~ ~~~ $a = range(0,3); xdebug_debug_zval('a'); $b = $a; xdebug_debug_zval('a'); $c = &$a; xdebug_debug_zval('a'); 打印结果 : a: (refcount=1, is_ref=0) array (size=4) 0 => (refcount=0, is_ref=0)int 0 1 => (refcount=0, is_ref=0)int 1 2 => (refcount=0, is_ref=0)int 2 3 => (refcount=0, is_ref=0)int 3 a: (refcount=2, is_ref=0) array (size=4) 0 => (refcount=0, is_ref=0)int 0 1 => (refcount=0, is_ref=0)int 1 2 => (refcount=0, is_ref=0)int 2 3 => (refcount=0, is_ref=0)int 3 a: (refcount=2, is_ref=1) array (size=4) 0 => (refcount=0, is_ref=0)int 0 1 => (refcount=0, is_ref=0)int 1 2 => (refcount=0, is_ref=0)int 2 3 => (refcount=0, is_ref=0)int 3 ~~~ ### 六. 对象本身就是引用传值 ~~~ class Person { public $name = "zhangsan"; } $p1 = new Person; xdebug_debug_zval('p1'); $p2 = $p1; xdebug_debug_zval('p1'); $p2->name = "zhouliuwan"; xdebug_debug_zval('p1'); 打印结果 : p1:(refcount=1, is_ref=0) object(Person)[1] public 'name' => (refcount=1, is_ref=0)string 'zhangsan' (length=8) p1:(refcount=2, is_ref=0) object(Person)[1] public 'name' => (refcount=1, is_ref=0)string 'zhangsan' (length=8) p1:(refcount=2, is_ref=0) object(Person)[1] public 'name' => (refcount=0, is_ref=0)string 'zhouliuwan' (length=10) // name值已经发生改变 ~~~