PHP 语法引用使用及实现
说明这里基于 php7.2.5 进行测试,php7 之后内部结构变化应该不是太大,但与 php5.X 有差别。 什么是引用在 PHP 中引用是一种数据类型 (结构),是指 指向同一个类型的数据结构,来看具体存储结构 struct _zend_reference { // 引用计数用于垃圾回收 先忽略 zend_refcounted_h gc; // zval是另一个变量 zval还记得吗 存储变量的结构 // 这里val指向另一个zval zval val; };
忘了的这里看 zval 如何使用// 定义变量 $a = "hello"; // &生成引用变量 $b = &$a; echo $b; echo PHP_EOL; php hello.php hello
结果大家都知道,$b 与 $a 的值是相同的,而且你还知道,修改 $b 同时也会作用与 $a. $a = "hello"; $b = &$a; echo "b:".$b; echo PHP_EOL; $b = "world"; echo "a:".$a; echo PHP_EOL; php hello.php b:hello a: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("%pn",&str); } gcc pointer.c -o pointer ./pointer 0x7ffee6d3292a
但是 PHP 的 & 并不是获取变量的地址,这是需要注意的。 ? unset 引用变量unset($b); echo "a:".$a; echo PHP_EOL; echo "b:".$b; echo PHP_EOL; php hello.php a:world PHP 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.php Array ( [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 中通过 & 获取对变量的引用,实质是多个变量通过中间引用类型(不是指向内存地址),指向同一个值。PHP高级开发工程师简历打造,祝你金三银四跳槽加薪 ? (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |