资讯专栏INFORMATION COLUMN

php 变量分离和引用

QiuyueZhong / 3401人阅读

摘要:变量的分离和引用今天看了一下鸟哥博客变量的分离和引用的内容就做了一个笔记如果我们我们创建一个变量就分配一次内存那么像上边的代码那么就会造成内存的极大浪费中的变量是一个指向的符号那么我们就可以在中来优化上边的代码的中有一个字段用来记录当前被引

PHP 变量的分离和引用

今天看了一下鸟哥博客变量的分离和引用的内容, 就做了一个笔记!

$var = "I have a dream";
$var2 = $var;
$var3 = $var;

如果我们我们创建一个变量就分配一次内存, 那么像上边的代码,那么就会造成内存的极大浪费. php中的变量是一个指向zval的符号, 那么我们就可以在zval中来优化上边的代码!
phpzval中有一个recount字段, 用来记录当前zval被引用的次数

$var = "abc";           //refcount = 1
$varCopy = $var;        //refcount = 2

创建第一个变量$varrefcount的值为1, 当创建第二个变量$varCopy时, refcount的值为2.我们怎么能查看到这个值呢, 可以通过php提供的debug_zval_dump输出变量的内容和refcount

$var = "abc";               //refcount = 1
debug_zval_dump($var);      //string(3) "abc" refcount(2)
$varCopy = $var;            //refcount = 2
debug_zval_dump($var);      //string(3) "abc" refcount(3)

为什么打印的结果和我们预想的结果不一致呢, 函数debug_zval_dump有一个值传递的形参, 就相当于又执行了一次$arg = $var, 执行这段代码的时候$varrefcount又增加了1,所以在debug_zval_dump内部打印的结果就比实际的要大1.如果我们对一个变量进行unset那么会是一种什么样的效果呢

$var = "abc";
$varCopy = $var;
unset($var);
debug_zval_dump($varCopy);      //string(3) "abc" refcount(2)

如果像下边这段代码会发生什么呢:

    $var = "abc";
    $varCopy = $var;
    $var = 1;

如果一个变量被重新赋值, 在赋值的过程中会首先检测refcount的值, 如果refcount大于1, php就会执行一个分离过程.上边的代码在执行到第三行的时候, php发现$var指向的zvalrefcount大于1, 那么php就会复制一个新的zval出来, 将原来的zvalrefcount减1,并修改变量符号表, 是$var指向新的zval结构 1.这样原来的$var$varCopy就各自指向了不同的结构. 这个就是

copy one write 也叫写时复制

如果我们再加上引用的情况, 那么整个过程就会更加复杂!

$var = "abc";
$varRef = &$var;
$varRef = 1;

最终$var的结果是1, 这个过程被称为

change on write 写时改变

这次的复制是不需要进行变量分离的,需要用到zvalis_ref字段, 对于上边的代码, 当第二行执行以后, $var所代表的zvalrefcount变为2, 同时设置is_ref为1.
第三行的时候, php会首先检查$varRefzvalis_ref字段,如果为1, 则不分离.

$var = "abc";
$varCopy = $var;
$varRef = &$var;

上边的情况, 存在copy on write 同时也有change on write, 是怎么运作的呢.
当执行第二行的时候和前边的copy on write一样, $var$varCopy指向相同的zval,refcount为2
当执行第三行的时候, php发现要操作的zval($var所指向的zval)的refcount大于1, php就会执行分离操作, 把$varCopy分离出去, 并将$var$varRef做change on write关联, 也就是refcount=2, is_ref=1
如果整个过程反过来2

$var = "abc";       //refcount=1, is_ref=0
$varRef = &$var;    //refcount=2, is_ref=1
$varCopy = $var;    //refcont=1, is_ref=0

第三行代码, 因为上边的变量$var对应的zval有is_ref的存在, 那么当前的变量就会直接复制一份出来, 而不会触发copy on write机制.

我们在看一段代码

$var = "abc";
$varRef = &$var;
debug_zval_dump($var);  //string(3) "abc" refcount(1)

这个结果和预想的又有所差别, 是什么原因的? debug_zval_dump() 需要一个值传递的形参, 那么执行debug_zval_dump($var)的时候就相当于debug_zval_dump($arg = $var) 这样就会造成变量的分离,在debug_zval_dump($arg)就相当于对一个全新的变量执行!


这个地方按我的理解应该是要全新生成一个zval, 然后修改原来的zval的refcount ↩

这个是我自己猜想的, 不知道是否正确.请输入代码

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/21216.html

相关文章

  • zval _ 引用计数 _ 变量分离 _ 写时拷贝

    摘要:引用计数变量分离写时拷贝我们一步步来理解语言特性是脚本语言,所谓脚本语言,就是说并不是独立运行的,要运行代码需要解析器,用户编写的代码最终都会被解析器解析执行的执行是通过引擎,是用编写的用户编写的代码最终都会被翻译成的虚拟机的虚拟指令来执行 zval、引用计数、变量分离、写时拷贝我们一步步来理解1、php语言特性PHP是脚本语言,所谓脚本语言,就是说PHP并不是独立运行的,要运行PHP...

    happyfish 评论0 收藏0
  • PHP_Smarty

    摘要:体现了业务与显示的分离,尽量分离。就负责判断条件,并取出数据来。显示的工作尽量靠前页面缓存缓存,重要概念。减轻了数据库的压力。控制局部不缓存在标签中控制,该标签不缓存。模板调用特殊方法使用对象注册的方式来解决。文件命名函数名定 模板 数据与表现层的标签分离 smarty是PHP 与 HTML代码的分离 小型模板类 $smarty 的工作流程: 把需要显示的全局变量,赋值塞到对象内部的...

    printempw 评论0 收藏0
  • PHP执行原理

    摘要:执行原理是一门应用非常简单,开发效率极高的一门语言,其弱类型的变量能省去程序员大量的定义变量类型转换等的时间和精力。程序最终被翻译为一组处理函数的顺序执行。只有减为时才会真正执行销毁操作。 PHP执行原理 php是一门应用非常简单,开发效率极高的一门语言,其弱类型的变量能省去程序员大量的定义变量、类型转换等的时间和精力。它是一种适用于web开发的动态语言。 1. php设计的原理和特点...

    silvertheo 评论0 收藏0
  • PHP垃圾回收机制

    摘要:在中算法,当节点缓冲区满了之后,垃圾分析算法就会启动,并且会释放掉发现的垃圾,从而回收内存。在编程中程序员不需要手动处理内存资源分配与释放,意味着本身实现了垃圾回收处理机制。 PHP是一种弱类型的脚本语言,弱类型不表示PHP变量没有类型的区别,PHP变量有8种原始类型:四种标量类型: boolean(布尔值) integer(整型) float(浮点型) 两种复合类型: arra...

    luck 评论0 收藏0
  • 史上最难PHP笔试题答案

    摘要:支持字符串哈希列表集合有序集合等数据结构,目前不支持事务。是多入口以下关于表驱动法的描述,错误的是表驱动法可以作为复杂继承结构的替代方案,难点在于一个经过深思熟虑的查询表。表驱动法查找无规则分布的数据采用阶梯访问的方法最佳。 1、有关PHP字符串的说法,不对的是: CA、如果一个脚本的编码是ISO-8859-1,则其中的字符串也会被编码为 ISO-8859-1。B、PHP的字符串在内部...

    yuxue 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<