在PHP面试中,经常会遇到这样一道问题:
什么是变量引用,用什么符号表示?
这个其实很简单,变量引用简单来说就是不同的变量名称指向同一个值。用&符号表示。
初学PHP,都知道变量的声明与赋值为:
$a = str_replace("hello world",40);
我们可以将值再赋给$b
$b = $a;
这样$a,$b都等于hello world,那在内存中是不是开辟了2个空间来存储呢?我们可以使用memory_get_usage()来查看:
$a =str_replace( 'hello world',40);
var_dump(memory_get_usage());
$b = $a;
var_dump(memory_get_usage());
你会发现内存的值没有变化。也就是说变量a和b都指向了同一个内存地址。
这里设计PHP的一个重要原则,是COW,即copy on write,意思就是说只有在真的写入的时候,才会复制出一块内存地址。
那我们继续看:
var_dump(memory_get_usage());
$a = str_repeat('hello world',40);
var_dump(memory_get_usage());
$b = $a;
var_dump(memory_get_usage());
$a = str_repeat('hello teacher',40);
var_dump(memory_get_usage());
以上的代码,就会发现当$a重新赋值时,内存占用发生了变化 。
那再来看变量引用
var_dump(memory_get_usage());
$a = str_repeat('hello world',1);
var_dump(memory_get_usage());
$b = &$a;
var_dump(memory_get_usage());
$a = str_repeat('hello teacher',1);
var_dump(memory_get_usage());
echo $a;
echo '----------';
echo $b;
使用&符号以后,变量a和b使用一块内存地址,a发生变化后,b也随着变化.
往底层来考虑
zval是php中最重要的数据结构之一。
struct _zval_struct {
zvalue_value value; /* value */
zend_uint refcount__gc; /* variable ref count */
zend_uchar type; /* active type */
zend_uchar is_ref__gc; /* if it is a ref variable */
};
typedef struct _zval_struct zval;
以上是一段C语言代码,这是zval的定义,一共有四个值,
zvalue是变量的实际值
uchar 是变量的的类型,比如PHP中的常用变量:bool、int、float、array、string、object、NULL等
refcount_gc:是一个计数器,当我们把变量覆值给另一个变量时,计数器加1,unset计数器减1,简单来说就是有多少个变量指向它。
is_ref__gc:这个值分为0和1,代表是否为引用变量
结论就是PHP底层的数据结构设计 决定了引用变量和变量赋值的原理。
注:对象类型本身就是引用传递。