iis服务器助手广告
返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >PHP中的引用计数是什么
  • 419
分享到

PHP中的引用计数是什么

2023-06-20 14:06:38 419人浏览 独家记忆
摘要

本篇内容主要讲解“PHP中的引用计数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“php中的引用计数是什么”吧!什么是引用计数在PHP的数据结构中,引用计数就是指每一个变量,除了保存了它们

本篇内容主要讲解“PHP中的引用计数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习php中的引用计数是什么”吧!

什么是引用计数

在PHP的数据结构中,引用计数就是指每一个变量,除了保存了它们的类型和值之外,还额外保存了两个内容,一个是当前这个变量是否被引用,另一个是引用的次数。为什么要多保存这样两个内容呢?当然是为了垃圾回收(GC)。

也就是说,当引用次数为0的时候,这个变量就没有再被使用了,就可以通过 GC 来进行回收,释放占用的内存资源。

任何程序都不能无限制的一直占用着内存资源,过大的内存占用往往会带来一个严重的问题,那就是内存泄露,而 GC 就是PHP底层自动帮我们完成了内存的销毁,而不用像 C 一样必须去手动地 free 。

怎么查看引用计数?

我们需要安装 xdebug 扩展,然后使用 xdebug_debug_zval() 函数就可以看到指定内存的详细信息了,比如:

$a = "I am a String";xdebug_debug_zval('a');// a: (refcount=1, is_ref=0)='I am a String'

从上述内容中可以看出,这个 $a 变量的内容是 I am a String 这样一个字符串。而括号中的 refcount 就是引用次数,is_ref 则是说明这个变量是否被引用。我们通过变量赋值来看看这个两个参数是如何变化的。

$b = $a;xdebug_debug_zval('a');// a: (refcount=1, is_ref=0)='I am a String'$b = &$a;xdebug_debug_zval('a');// a: (refcount=2, is_ref=1)='I am a String'

当我们进行普通赋值后,refcount 和 is_ref 没有任何变化,但当我们进行引用赋值后,可以看到 refcount 变成了2,is_ref 变成了1。这也就是说明当前的 \a变量被引用赋值了,它的内存符号表服务于a 变量被引用赋值了,它的内存符号表服务于a变量被引用赋值了,它的内存符号表服务于a 和 $b 两个变量。

$c = &$a;xdebug_debug_zval('a');// a: (refcount=3, is_ref=1)='I am a String'unset($c, $b);xdebug_debug_zval('a');// a: (refcount=1, is_ref=1)='I am a String'$b = &$a;$c = &$a;$b = "I am a String new";xdebug_debug_zval('a');// a: (refcount=3, is_ref=1)='I am a String new'unset($a);xdebug_debug_zval('a');// a: no such symbol

继续增加一个 c的引用赋值,可以看到refcount会继续增加。然后unsetc 的引用赋值,可以看到 refcount 会继续增加。然后 unset 掉c的引用赋值,可以看到refcount会继续增加。然后unset掉b 和 $c 之后,refcount 恢复到了1,不过这时需要注意的是,is_ref 依然还是1,也就是说,这个变量被引用过,这个 is_ref 就会变成1,即使引用的变量都已经 unset 掉了这个值依然不变。

最后我们 unset 掉 $a ,显示的就是 no such symbol 了。当前变量已经被销毁不是一个可以用的符号引用了。(注意,PHP中的变量对应的是内存的符号表,并不是真正的内存地址)

对象的引用计数

和普通类型的变量一样,对象变量也是使用同样的计数规则。

// 对象引用计数class A{}$objA = new A();xdebug_debug_zval('objA');// objA: (refcount=1, is_ref=0)=class A {  }$objB = $objA;xdebug_debug_zval('objA');// objA: (refcount=2, is_ref=0)=class A {  }$objC = $objA;xdebug_debug_zval('objA');// objA: (refcount=3, is_ref=0)=class A {  }unset($objB);class C{}$objC = new C;xdebug_debug_zval('objA');// objA: (refcount=1, is_ref=0)=class A {  }

不过这里需要注意的是,对象的符号表是建立的连接,也就是说,对 objC进行重新实例化或者修改为NULL,并不会影响objC 进行重新实例化或者修改为 NULL ,并不会影响objC进行重新实例化或者修改为NULL,并不会影响objA 的内容。对象进行普通赋值操作也是引用类型的符号表赋值,所以我们不需要加 & 符号。

数组的引用计数

// 数组引用计数$arrA = [    'a'=>1,    'b'=>2,];xdebug_debug_zval('arrA');// arrA: (refcount=2, is_ref=0)=array (//     'a' => (refcount=0, is_ref=0)=1, //     'b' => (refcount=0, is_ref=0)=2// )$arrB = $arrA;$arrC = $arrA;xdebug_debug_zval('arrA');// arrA: (refcount=4, is_ref=0)=array (//     'a' => (refcount=0, is_ref=0)=1, //     'b' => (refcount=0, is_ref=0)=2// )unset($arrB);$arrC = ['c'=>3];xdebug_debug_zval('arrA');// arrA: (refcount=2, is_ref=0)=array (//     'a' => (refcount=0, is_ref=0)=1, //     'b' => (refcount=0, is_ref=0)=2// )// 添加一个已经存在的元素$arrA['c'] = &$arrA['a'];xdebug_debug_zval('arrA');// arrA: (refcount=1, is_ref=0)=array (//     'a' => (refcount=2, is_ref=1)=1, //     'b' => (refcount=0, is_ref=0)=2, //     'c' => (refcount=2, is_ref=1)=1// )

调试数组的时候,我们会发现两个比较有意思的事情。

一是数组内部的每个元素又有单独的自己的引用计数。这也比较好理解,每一个数组元素都可以看做是一个单独的变量,但数组就是这堆变量的一个哈希集合。如果在对象中有成员变量的话,也是一样的效果。当数组中的某一个元素被 & 引用赋值给其他变量之后,这个元素的 refcount 会增加,不会影响整个数组的 refcount 。

二是数组默认上来的 refcount 是2。其实这是 PHP7 之后的一种新的特性,当数组定义并初始化后,会将这个数组转变成一个不可变数组(immutable array)。为了和普通数组区分开,这种数组的 refcount 是从2开始起步的。当我们修改一下这个数组中的任何元素后,这个数组就会变回普通数组,也就是 refcount 会变回1。这个大家可以自己尝试下,关于为什么要这样做的问题,官方的解释是为了效率,具体的原理可能还是需要深挖 PHP7 的源码才能知晓。

关于内存泄露需要注意的地方

其实 PHP 在底层已经帮我们做好了 GC 机制就不需要太关心变量的销毁释放问题,但是,千万要注意的是对象或数组中的元素是可以赋值为自身的,也就是说,给某个元素赋值一个自身的引用就变成了循环引用。那么这个对象就基本不太可能会被 GC 自动销毁了。

// 对象循环引用class D{    public $d;}$d = new D;$d->d = $d;xdebug_debug_zval('d');// d: (refcount=2, is_ref=0)=class D { //     public $d = (refcount=2, is_ref=0)=... // }// 数组循环引用$arrA['arrA'] = &$arrA;xdebug_debug_zval('arrA');// arrA: (refcount=2, is_ref=1)=array (//     'a' => (refcount=0, is_ref=0)=1, //     'b' => (refcount=0, is_ref=0)=2, //     'arrA' => (refcount=2, is_ref=1)=...// )

不管是对象还是数组,在打印调试时出现了 ... 这样的省略号,那么你的程序中就出现了循环引用。在之前的文章 关于PHP中对象复制的那点事儿 中我们也讲过这个循环引用的问题,所以这个问题应该是我们在日常开发中应该时刻关注的问题。

总结

引用计数是了解垃圾回收机制的前提条件,而且正是因为现代语言中都有一套类似的垃圾回收机制才让我们的编程变得更加容易且安全。那么有人说了,日常开发根本用不到这些呀?用不到不代表不应该去学习,就像循环引用这个问题一样,当代码中充斥着大量的类似代码时,系统崩溃只是迟早的事情,所以,这些知识是我们向更高级的程序进阶所不可或缺的内容。

测试代码:https://GitHub.com/zhangyue0503/dev-blog/blob/master/php/202004/source/PHP%E7%9A%84%E5%BC%95%E7%94%A8%E8%AE%A1%E6%95%B0%E6%98%AF%E4%BB%80%E4%B9%88%E6%84%8F%E6%80%9D%EF%BC%9F.php参考文档:Https://www.php.net/manual/zh/features.gc.refcounting-basics.phphttps://www.jianshu.com/p/52450a61354d

到此,相信大家对“PHP中的引用计数是什么”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

--结束END--

本文标题: PHP中的引用计数是什么

本文链接: https://www.lsjlt.com/news/297217.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • PHP中的引用计数是什么
    本篇内容主要讲解“PHP中的引用计数是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“PHP中的引用计数是什么”吧!什么是引用计数在PHP的数据结构中,引用计数就是指每一个变量,除了保存了它们...
    99+
    2023-06-20
  • PHP中引用计数指的是什么意思
    这篇文章将为大家详细讲解有关PHP中引用计数指的是什么意思,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。php是什么语言php,一个嵌套的缩写名称,是英文超级文本预处理语言(PHP:Hypertext P...
    99+
    2023-06-14
  • php中索引数组的作用是什么
    这篇文章给大家介绍php中索引数组的作用是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。PHP开发环境搭建工具有哪些一、phpStudy,是一个新手入门最常用的开发环境。二、WampServer,WampServe...
    99+
    2023-06-14
  • python中什么是引用计数器机制
    本篇文章为大家展示了python中什么是引用计数器机制,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。python可以做什么Python是一种编程语言,内置了许多有效的工具,Python几乎无所不能,...
    99+
    2023-06-14
  • Python引用计数机制是什么
    Python的引用计数机制是一种自动内存管理机制,用于跟踪对象的引用数量。每个对象都有一个引用计数,当一个对象被创建时,引用计数为1...
    99+
    2023-10-25
    Python
  • PHP中索引数组的优点是什么
    这篇文章给大家介绍PHP中索引数组的优点是什么,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。PHP开发环境搭建工具有哪些一、phpStudy,是一个新手入门最常用的开发环境。二、WampServer,WampServe...
    99+
    2023-06-14
  • php中什么是引用传参
    小编给大家分享一下php中什么是引用传参,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是引用传参:在设定函数形参时,如果在形参变量之前添加符号,就表示实参传递...
    99+
    2023-06-15
  • 详解PHP的引用计数
    目录什么是引用计数怎么查看引用计数?对象的引用计数数组的引用计数关于内存泄露需要注意的地方总结什么是引用计数 在PHP的数据结构中,引用计数就是指每一个变量,除了保存了它们的类型和...
    99+
    2024-04-02
  • PHP7中zval结构和引用计数机制是什么
    这篇文章主要介绍PHP7中zval结构和引用计数机制是什么,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!最近在查阅 PHP7 垃圾回收的资料的时候,网上的一些代码示例在本地环境下运行时出现了不同的结果,使我一度非常迷...
    99+
    2023-06-14
  • PHP中引用符号(&)的作用是什么
    本篇文章给大家分享的是有关PHP中引用符号(&)的作用是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。按位与$a & $b 将把 $a 和 $b 中都为1的...
    99+
    2023-06-15
  • Python中怎么引用计数
    Python中怎么引用计数,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。回顾内存地址Python中的任何变量都有对应的内存引用,也就是内存地址。如果不是容器类型,那么直接引...
    99+
    2023-06-16
  • Oracle数据库中索引的常见执行计划是什么
    这篇文章将为大家详细讲解有关Oracle数据库中索引的常见执行计划是什么,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。今天主要介绍下Oracle索引的常见执...
    99+
    2024-04-02
  • MySQL数据库索引的设计原则是什么
    本篇内容主要讲解“MySQL数据库索引的设计原则是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“MySQL数据库索引的设计原则是什么”吧!为了使索引的使用效...
    99+
    2024-04-02
  • css中的计数器是什么
    这篇文章给大家分享的是有关css中的计数器是什么的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。   css计数器是什么?   计数器是css3提供的一个强大的工具,是一种可以...
    99+
    2024-04-02
  • JavaScript中的弱引用和强引用是什么
    本篇内容介绍了“JavaScript中的弱引用和强引用是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!...
    99+
    2024-04-02
  • php中单双引号的区别是什么
    在 php 中,单引号用于创建不进行转义或变量解析的简单字符串,而双引号则支持这些功能并允许创建复杂字符串。总体上,使用单引号的性能略优于双引号,因此对于简单字符串建议使用单引号。 P...
    99+
    2024-04-29
  • PHP中引号转义的原理是什么
    本篇文章给大家分享的是有关PHP中引号转义的原理是什么,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。PHP中有三个设置可以实现自动对’(单引号),”(双引号...
    99+
    2023-06-17
  • 索引函数在 Java 中的作用是什么?
    在 Java 中,索引函数的作用是帮助程序员快速查找和获取数据。通常情况下,我们使用索引函数来优化程序的性能,特别是在大型数据集合中搜索数据时。 Java 中有很多索引函数可以使用,包括数组索引、哈希表索引、树索引等。在本文中,我们将着重...
    99+
    2023-09-02
    索引 函数 api
  • 在php中单引号和双引号的区别是什么
    这篇“在php中单引号和双引号的区别是什么”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“在php中单引号和双引号的区别是什么”,小编整理了以下知识点,请大家跟着小编的步伐一步一步的慢慢理解,接...
    99+
    2023-06-06
  • php中sort函数的作用是什么
    php中sort函数的作用是什么?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。php是什么语言php,一个嵌套的缩写名称,是英文超级文本预处理语言(PHP:Hypertext ...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作