我读了很多关于如何在机器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 = 0
和is_ref = 1
一起使用。
如果is_ref = 0
和refcount > 1
在创建硬链接时,我们会获得一个新的zval容器,如果我们按值进行赋值 - 将不会创建新的zval容器。
如果is_ref = 1
和refcount > 1
创建硬链接时未创建新的zval,则使用旧的。如果我们不创建硬链接,但是按值分配 - 这意味着我们创建了新的zval容器。
P.S我写这篇文章是为了表明理解我要求并说明为什么我不理解上面编写的代码的行为
答案 0 :(得分:10)
答案很简单,正如您对问题的评论中所解释的那样。虽然,我想我明白你的困惑来自哪里,所以让我们打破这个。 :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)。
正如我们试图向您解释的那样,混淆源于这样一个事实:原始问题背后的前提是有缺陷的:您在这些示例中没有引用变量,您引用的内存区域包含最初与所述变量关联的数据。所以你要用另一个覆盖一个(原始的)" hardlink"由于内部PHP的原因,唯一的区别是后者被标记为这样。 (在refcounts> 1的情况下,引用不会在写入时被复制。)