之前的文章中,我们已经学习过引用和引用传值相关的知识。我们知道,PHP 中没有纯引用(指针),不管是对象,还是用引用符号 & 赋值的变量,都是对一个符号表的引用。而今天,我们要学习的是另一种引用形式:弱引用。

什么是弱引用

弱引用允许程序员保留对对象的引用,而该对象不会阻止对象被销毁;它们对于实现类似缓存的结构非常有用。

这是比较官方的解释。从这个说明中,我们可以看出,弱引用也是一种引用形式,但是,如果我们销毁了原来的对象,那么弱引用对象也会被销毁,就像普通的值对象赋值一样。如果没有看过之前的文章,或者对 PHP 中的引用不太熟悉的朋友可能需要再了解一下 PHP 中引用相关的知识。下面,我们直接通过示例来看一下。

WeakReference

$obj = new stdClass;
$weakref = $obj; var_dump($weakref);
// object(stdClass)#1 (0) {
// } unset($obj);
var_dump($weakref);
// object(stdClass)#1 (0) {
// } $obj1 = new stdClass;
$weakref = WeakReference::create($obj1); var_dump($weakref->get());
// object(stdClass)#2 (0) {
// } unset($obj1);
var_dump($weakref->get());
// NULL $weakref = WeakReference::create(new stdClass);
var_dump($weakref->get());
// NULL

第一个对象 \$obj 我们进行直接的赋值引用,也就是 PHP 默认的对象赋值。这时候,$weakref 保存的是对象符号表的引用。当我们 unset() 掉 $obj 时,$weakref 依然能够正常使用。也就是说,$weakref 对 $obj 原始对象的内存引用依然保持着。不管我们怎么 unset() 原始的 $obj ,都只是切断了 $obj 的引用符号表,对真正的对象没有影响,垃圾回收器也不会彻底的回收最最原始的 $obj 对象内容。

第二个对象我们使用的是 WeakReference 的 create() 方法来创建的弱引用,当我们销毁 $obj1 后,$weakref 也会变成 NULL 。这就是弱引用的作用!

它可以让垃圾回收器正常的回收,它可以避免循环引用带来的内存泄漏问题,它能让引用表现为类似于 C 中的指针操作一样。

最后一段代码是我们通过 WeakReference::create() 中直接使用 new 来创建对象。这种形式是不行的,会一直返回 NULL 。因为弱引用是通过变量来创建的,它指向的是原始对象的符号表,而变量和对象之间的符号表连接才是弱引用关心的内容,它会根据符号表的状态来判断当前的状态。如果原始对象变量切断了与符号表的连接,那么弱引用的变量也会同步切断,这样,垃圾回收器就能正常的清理这个已经没有任何引用计数的对象了。

注意

这里需要注意的是,上面的测试代码必须在 PHP7.4 及以上版本才有用,WeakReference 类是 PHP7.4 新增加的内容。之前的版本需要安装 WeakRef 这个扩展才能实现弱引用的能力,具体的内容可以查阅下方链接中的相关的文档。

测试代码:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202006/source/%E5%AD%A6%E4%B9%A0PHP%E5%BC%B1%E5%BC%95%E7%94%A8%E7%9A%84%E7%9F%A5%E8%AF%86.php

参考文档:

https://www.php.net/manual/en/class.weakreference.php

https://www.php.net/manual/zh/book.weakref.php

学习PHP弱引用的知识的更多相关文章

  1. Java学习之强引用,弱引用,软引用 与 JVM

    1.java内存管理分为内存分配和内存回收,都不需要程序员负责. 2.垃圾回收的机制主要是看对象是否有引用指向该对象.  java对象的引用包括  强引用 软引用 弱引用 虚引用 3.强引用 是指创建 ...

  2. 九、Android学习笔记_ Android开发中使用软引用和弱引用防止内存溢出

    在<Effective Java 2nd Edition>中,第6条“消除过期的对象引用”提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象 ...

  3. C#学习笔记(十四):GC机制和弱引用

    垃圾回收(GC) 垃圾回收即Garbage Collector,垃圾指的是内存中已经不会再使用的对象,通过收集释放掉这些对象占用的内存. GC以应用程序的root为基础,遍历应用程序在Heap上动态分 ...

  4. JVM学习之强引用、弱引用、软引用、虚引用

    转自:http://my.oschina.net/ydsakyclguozi/blog/404389 多谢博主分享 1.强引用(StrongReference) 强引用是使用最普遍的引用.如果一个对象 ...

  5. Android学习笔记之SoftReference软引用,弱引用WeakReference

    SoftReference可以用于bitmap缓存 WeakReference 可以用于handler 非静态内部类和匿名内部类容易造成内存泄漏 private Handler mRemoteHand ...

  6. Android学习笔记_78_ Android开发中使用软引用和弱引用防止内存溢出

    在<Effective Java 2nd Edition>中,第6条“消除过期的对象引用”提到,虽然Java有 垃圾回收机制,但是只要是自己管理的内存,就应该警惕内存泄露的问题,例如的对象 ...

  7. Java学习|强引用,软引用,弱引用,幻想引用有什么区别?

    在Java语言中,除了基本数据类型外,其他的都是指向各类对象的对象引用:Java中根据其生命周期的长短,将引用分为4类. 1 强引用 特点:我们平常典型编码Object obj = new Objec ...

  8. 【JVM学习】3.深入解析强引用、软引用、弱引用、幻象引用

    来源:公众号:猿人谷 关于强引用.软引用.弱引用.幻象引用的区别,在很多公司的面试题中经常出现,可能有些小伙伴觉得这个知识点比较冷门,但其实大家在开发中经常用到,如new一个对象的时候就是强引用的应用 ...

  9. weak 弱引用的实现方式

    来源:冬瓜争做全栈瓜 链接:https://desgard.com/weak/ 对于 runtime 的分析还有很长的路,最近在写 block 系列的同时,也回顾一下之前疏漏的细节知识.这篇文章是关于 ...

随机推荐

  1. STM32启动代码分析及其汇编学习-ARM

    STM32 启动代码 Author By YuCloud 边看启动文件边学汇编 汇编 see ARM: Assembler User Guide see: https://blog.csdn.net/ ...

  2. MyBatis学习04(注解开发)

    7.使用注解开发 7.1 面向接口编程 根本原因 : 解耦 , 可拓展 , 提高复用 , 分层开发中 , 上层不用管具体的实现 , 大家都遵守共同的标准 , 使得开发变得容易 , 规范性更好 在一个面 ...

  3. 如何快速方便的生成好看的接口文档(apipost生成文档)

    一键生成文档 我们在"2分钟玩转APIPOST"一讲中,简单介绍了如何生成并分享接口文档: 点击分享文档 复制并打开文档地址就可以看到了完整的接口文档. 本节课主要是讲解一些需要注 ...

  4. noip模拟12[简单的区间·简单的玄学·简单的填数]

    noip模拟12 solutions 这次考试靠的还是比较好的,但是还是有不好的地方, 为啥嘞??因为我觉得我排列组合好像白学了诶,文化课都忘记了 正难则反!!!!!!!! 害没关系啦,一共拿到了\( ...

  5. 题解 数列 及exgcd总结

    传送门 自闭了--考场上exgcd打错然后对着屏幕自闭了一个小时不知道它为什么解得不对 开始恶补: 对于方程 \(a*x+b*y=c\) ,就等价于 \(a*x \equiv c\pmod{b}\) ...

  6. 什么是TCP,什么是UDP,它们两者的区别? 三次握手

    TCP: 定义: TCP(Transmission Control Protocol 传输控制协议)是一种面向连接的.可靠的.基于字节流的传输层通信协议,由IETF的RFC 793定义. TCP编程的 ...

  7. ASP.NET Core:中间件

    一.什么是中间件 我们都知道,任何的一个web框架都是把http请求封装成一个管道,每一次的请求都是经过管道的一系列操作,最终才会到达我们写的代码中.而中间件就是用于组成应用程序管道来处理请求和响应的 ...

  8. 踩坑记录之 -- String.IndexOf 在 .Net5 和 .Netcore3 中返回值不一样

    .Net Core3.1 下 运行此段代码 class Program { static void Main(string[] args) { // .NET Core 3.1 string s = ...

  9. C#基础知识---Lambda表达式

    一.Lambda表达式简介 Lambda表达式可以理解为匿名函数,可以包含表达式和语句.它提供了一种便利的形式来创建委托. Lambda表达式使用这个运算符--- "=>", ...

  10. C#与.NET、CLR、CLI是什么关系?什么是.NET框架

    1.C#与.NET.CLR.CLI是什么关系?什么是.NET框架?      这个问题好专业啊!一句话两句话还真不好说清.您听说过C++中有个COM的概念吧?您听说过JAVA里的虚拟机吧?CLR(公共 ...