香雨站

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 112|回复: 0

PHP 语法引用使用及实现

[复制链接]

2

主题

6

帖子

8

积分

新手上路

Rank: 1

积分
8
发表于 2023-1-9 15:42:55 | 显示全部楼层 |阅读模式
说明

这里基于 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("%p\n", &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: bunset ($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高级开发工程师简历打造,祝你金三银四跳槽加薪
更多学习内容请访问:
以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以加入我的官方群点击此处。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|香雨站

GMT+8, 2025-3-15 13:37 , Processed in 0.221459 second(s), 22 queries .

Powered by Discuz! X3.4

© 2001-2013 Comsenz Inc.. 技术支持 by 巅峰设计

快速回复 返回顶部 返回列表