在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底层的数据结构设计 决定了引用变量和变量赋值的原理。

注:对象类型本身就是引用传递。