关于 PHP 7 引用计数的困惑

Posted

技术标签:

【中文标题】关于 PHP 7 引用计数的困惑【英文标题】:Confusion about PHP 7 refcount 【发布时间】:2016-04-18 06:36:55 【问题描述】:
<?php

$s = "foobar";

$t = $s;

$u = $s;

echo PHP_VERSION . "\n";

debug_zval_dump($s);

xdebug_debug_zval('s');

在 PHP 5.6.16 中运行

在 PHP 7.0.2 中运行

我认为结果(PHP 7)应该是:

string(6) "foobar" refcount(4)
s: (refcount=3, is_ref=0)="foobar"

我想知道有什么不同?需要一些解释。非常感谢。

------更新------

Nikita Popov 的 - PHP 7 - 内部发生了什么变化? (P41)

http://www.slideshare.net/nikita_ppv/php-7-what-changed-internally

【问题讨论】:

php.net/manual/en/features.gc.refcounting-basics.php @devpro 这是 php 5.x 两者都没有改变......概念性 @devpro 为什么 refcount 是 0? nikic.github.io/2015/05/05/… 【参考方案1】:

在 PHP 7 中,zval 可以被引用计数,也可以不被引用。 zval 结构中有一个标志决定了这一点。

有些类型永远不会被引用。这些类型是 null、bool、int 和 double。

还有其他类型总是被引用。这些是对象、资源和引用。

还有一些类型,有时会被引用。这些是字符串和数组。

对于字符串,未引用的变体称为“内部字符串”。如果您使用的是 NTS(非线程安全)PHP 7 构建(通常是这样),则代码中的所有字符串文字都将被保留。这些实习字符串是去重的(即只有一个具有特定内容的实习字符串),并且保证在请求的整个持续时间内都存在,因此不需要对它们使用引用计数。如果您使用 opcache,这些字符串将存在于共享内存中,在这种情况下,您不能对它们使用引用计数(因为我们的引用计数机制是非原子的)。 Interned 字符串的虚拟引用计数为 1,这就是您在此处看到的。

对于数组,未引用的变体称为“不可变数组”。如果您使用 opcache,那么代码中的常量数组文字将被转换为不可变数组。再一次,它们存在于共享内存中,因此不能使用引用计数。不可变数组的虚拟引用计数为 2,因为它允许我们优化某些分离路径。

【讨论】:

以上是关于关于 PHP 7 引用计数的困惑的主要内容,如果未能解决你的问题,请参考以下文章

PHP的引用计数是什么意思?

关于自动引用计数,我需要了解啥?

python 关于循环引用以及标记清除的问题

使用 Cocoa 和 Objective-C 理解引用计数

swift进阶七:引用计数(Strong、Unowned、Weak)

关于智能指针类型shared_ptr的计数问题