【问题标题】:The variable refers to itself变量引用自身
【发布时间】:2017-03-09 07:05:57
【问题描述】:

看了很多关于如何在机器Zend内部构造变量的文章,发现了一件我无法解释的有趣的事情:

$int = 100;
xdebug_debug_zval('int'); /// int:(refcount=1,is_ref=0),int 100
$int = &$int;
xdebug_debug_zval('int'); /// int:(refcount=1,is_ref=1),int 100

事实证明,我们正在创建自身的链接?这怎么可能?

根据我所知清除信息:

通常is_ref = 1 仅当容器引用 zval 两个或多个硬链接变量时。

refcount - 是引用同一个 zval 容器的变量数量,但不同之处在于 is_ref = 0is_ref = 1 的引用计数不同。

如果is_ref = 0refcount > 1在创建硬链接时,我们会得到一个新的zval容器,如果我们通过一个值进行赋值-不会创建新的zval容器。

如果is_ref = 1refcount > 1在创建硬链接时没有创建新的zval,使用旧的。如果我们不创建硬链接,而是按值分配 - 这意味着我们创建了新的 zval 容器。

P.S 我写这篇文章是为了表明理解我问的问题,并说明为什么我不理解我上面写的代码的行为

【问题讨论】:

  • @RyanVincent 这可能吗?我怎样才能建立到同一个变量的硬链接,即它本身
  • @RyanVincent 我不明白你的意思。我知道一个变量拥有一个 zval 容器
  • 也许很有趣? PHP5 References Explained Visually。以后更容易理解。
  • @RyanVincent 我读了你的手册。但我的邪恶问题没有得到答案 - $int = &$int - 什么???这是?
  • @RyanVincent 但在我的情况下它并没有增加refcount,她仍然是 1

标签: php reference


【解决方案1】:

答案很简单,正如您问题的 cmets 中所解释的那样。不过,我想我明白你的困惑来自哪里,所以让我们分解一下。 :D

首先你给一个变量赋值,PHP 内部将这个值存储在一个内存段中,并增加引用这个地址的变量的计数器。 (参考计数 = 1)。到目前为止,一切都直截了当。
然后,您重新使用该变量来存储对该内存地址的引用(C 术语中的指针)。 PHP手册将此解释为存储对变量的引用,以使非C程序员更容易,这就是(我认为)您的困惑所在。内部没有对变量的引用,只有变量链接到的数据。由于您重新使用变量来存储此引用,因此引用计数不会增加:仍然只有一个变量指向此内存段。但是,它不再是普通的 PHP 变量,而是数据的引用(指针)。

编辑,添加:
实现相同结果的另一种方法是使用两个变量,然后使用unset 第一个变量。代码示例:

$a = 100; // refcount += 1
xdebug_debug_zval ('a'); // refcount=1,is_ref=0 -> zval {value=100,type=int (addr=0x78765asd)}

$b =& $a; // refcount += 1
xdebug_debug_zval ('a') // refcount=2,is_ref=0 -> zval {value=100,type=int (addr=0x78765asd)}
xdebug_debug_zval ('b') // refcount=2,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)}

unset ($a); // refcount -= 1
xdebug_debug_zval ('b') // refcount=1,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)}

仅使用一个变量将两个操作合并为一个,而不会破坏数据。因此:1 个变量 (refcount=1),它是对 data 本身的引用 (is_ref=1)。

正如我们试图向您解释的那样,混淆源于原始问题背后的前提存在缺陷这一事实:在这些示例中,您没有引用 变量,而是引用包含最初与所述变量相关联的数据的内存区域。所以你用另一个覆盖了一个(原始的)“硬链接”。唯一的区别是后者是这样标记的,因为 PHP 内部原因。 (在 refcounts > 1 的情况下,不会在写入时复制引用。)

【讨论】:

  • 如果我理解正确的话:在 php 中没有引用此类数据类型的概念,只有存储指向 zval 容器的指针的变量。但如果是这种情况,那么 php 中就没有特殊变量,并且会破坏你的概念
  • 你在想什么样的特殊变量?
  • @MaximPro 我已经更新了我的答案,以稍微不同但希望更清晰的方式为您解释它。
  • 你搞错了。最后一行// refcount=1,is_ref=1 -> zval {value=100,type=int (addr=0x78765asd)} - 我测试过了! is_ref=0
  • 是你说PHP中有“特殊变量”,我只是要求你澄清一下你的意思是“特殊变量”。也就是说,鉴于您不愿意接受任何与您认为正确的解释相悖的解释,恐怕我无法进一步帮助您。祝你一切顺利。
猜你喜欢
  • 2011-07-20
  • 2015-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-31
  • 1970-01-01
相关资源
最近更新 更多