解释

这里基于php7.2.5进行测试,php7之后内部构造变革该当不是太大,但与php5.X有差别。

什么是引用

php类引用天天一个PHP语法四引用应用及实现 Java

在PHP中引用是一种数据类型(构造),是指 指向同一个类型的数据构造,来看详细存储构造

struct _zend_reference { // 引用计数用于垃圾回收 先忽略zend_refcounted_h gc; // zval是另一个变量 zval还记得吗 存储变量的构造 // 这里val指向另一个zvalzval val;};

忘了的这里看zval

如何利用

// 定义变量$a = "hello";// &天生引用变量$b = &$a;echo $b;echo PHP_EOL;

php hello.phphello

结果大家都知道,$b与$a的值是相同的,而且你还知道,修正$b同时也会浸染与$a.

$a = "hello";$b = &$a;echo "b:".$b;echo PHP_EOL;$b = "world";echo "a:".$a;echo PHP_EOL;

php hello.phpb:helloa:world

如何实现

回顾zval的格式实行第一句时,天生的数据构造是这样的(简版示意图,真实构造繁芜)

当实行$b = &$a时,&$a会师长西席成引用类型的数据构造,然后引用的zval指向之前的hello的构造,$a,$b则共同指向引用构造。

那么在修正$b时,实际是修正了引用类型指向的zend_value,以是导致$a的值也发生了变革。

小结

php中利用&天生一个引用类型的数据,这个引用的zval指向原变量所指向的zval, 变量则会指向这个运用构造,当发生引用赋值之后,被赋值的变量也会指向这个引用,变动个中任何一个变量,所有的变量都会发生变革。
类似于你大名叫大壮, 小名叫小壮, 但是身份证都是xxoo100, 无论修正大壮还是小壮的身份证,他始终只有一个身份证。

扩展

我们可能听过取地址符这么一种说法,那么在C措辞或者GO中,通过利用&可以获取到变量的内存地址。

#include <stdio.h>#include<string.h>int main(){char str[] = "hello"; // &获取变量的内存地址printf("%p\n", &str);}

gcc pointer.c -o pointer./pointer0x7ffee6d3292a

但是PHP的&并不是获取变量的地址,这是须要把稳的。

unset引用变量

unset($b);echo "a:".$a;echo PHP_EOL;echo "b:".$b;echo PHP_EOL;

php hello.phpa:worldPHP Notice: Undefined variable: b

unset($b)之后,只是销毁了变量b及b对引用的指向,没有影响$a。

foreach中的引用

$list = [ ['id' => 3, 'total' => 3], ['id' => 4, 'total' => 4], ['id' => 5, 'total' => 5],];foreach ($list as $key => &$info) { $info['total'] = $info['total'] + 3;}print_r($list);// 一顿操作$info['name'] = "hello";print_r($info);

php hello.phpArray( [0] => Array ( [id] => 3 [total] => 6 ) [1] => Array ( [id] => 4 [total] => 7 ) [2] => Array ( [id] => 5 [total] => 8 ))Array( [id] => 5 [total] => 8 [name] => hello)

这里在foreach之后须要把info unset掉防止发生数据问题。

总结

PHP中通过&获取对变量的引用,本色是多个变量通过中间引用类型(不是指向内存地址),指向同一个值。