变量引用自身

2022-08-30 18:37:35

我读了很多关于如何在机器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

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

从我所知道的清晰信息:

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

refcount- 是引用同一 zval 容器的变量数,但不同值的 refcount 与 和 一起工作。is_ref = 0is_ref = 1

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

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

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


答案 1

答案非常简单,如您问题的评论中所述。不过,我想我明白你的困惑来自哪里,所以让我们分解一下。: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),这是对数据本身的引用 (is_ref=1)。

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


答案 2

推荐