Php Xdebug作为一个参考计数工具是有效的

Php Xdebug作为一个参考计数工具是有效的,php,xdebug,Php,Xdebug,文档中有一些片段说明了这是如何工作的,但有一点不清楚,我将在下面进行说明: /// Example 1 $a = 10; xdebug_debug_zval('a'); /// Output: /// a:(refcount=1, is_ref=0),int 10 /// Example 2 $a = 10; $b = 10; xdebug_debug_zval('a','b'); /// Output: /// a:(refcount=1, is_ref=0),int 10 /// b:(r

文档中有一些片段说明了这是如何工作的,但有一点不清楚,我将在下面进行说明:

/// Example 1
$a = 10;
xdebug_debug_zval('a');
/// Output:
/// a:(refcount=1, is_ref=0),int 10

/// Example 2
$a = 10;
$b = 10;
xdebug_debug_zval('a','b');
/// Output:
/// a:(refcount=1, is_ref=0),int 10
/// b:(refcount=1, is_ref=0),int 10

/// Example 3
$a = 10;
$b = $a;
xdebug_debug_zval('a','b');
/// Output:
/// a:(refcount=2, is_ref=0),int 10
/// b:(refcount=2, is_ref=0),int 10

/// Example 4
$a = 10;
$b = &$a;
xdebug_debug_zval('a','b');
/// Output:
/// a:(refcount=2, is_ref=1),int 10
/// b:(refcount=2, is_ref=1),int 10

/// Example 5
$a = 10;
$b = $a;
$c = $a;
xdebug_debug_zval('a','b','c');
/// Output:
/// a:(refcount=3, is_ref=0),int 10
/// b:(refcount=3, is_ref=0),int 10
/// c:(refcount=3, is_ref=0),int 10

/// Example 6
$a = 10;
$b = &$a;
$c = $a;
xdebug_debug_zval('a','b','c');
/// Output:
/// a:(refcount=2, is_ref=1),int 10
/// b:(refcount=2, is_ref=1),int 10
/// c:(refcount=1, is_ref=0),int 10

/// Example 7
$a = 10;
$b = &$a;
$c = &$a;
xdebug_debug_zval('a','b','c');
/// Output:
/// a:(refcount=3, is_ref=1),int 10
/// b:(refcount=3, is_ref=1),int 10
/// c:(refcount=3, is_ref=1),int 10
对于所有对我来说最不合逻辑的示例,结果都是
示例6
,我真的不明白为什么我们在没有获得以下条目的所有行时必须进行调试

/// Output:
/// a:(refcount=3, is_ref=1),int 10
/// b:(refcount=3, is_ref=1),int 10
/// c:(refcount=3, is_ref=0),int 10

解释是怎么回事?

如果你熟悉C语言,你必须从C语言的指针的角度来思考。PHP中的变量是指向ZVALs的指针,因此当您在PHP中“复制”变量时,PHP不会实际复制其值,而是增加refcount并复制指针。但是,如果您更改原始值,其他值也不会更改,因为PHP会执行一种称为“写入时复制”的操作(除非refcount=1

$a = 10;
$b = $a;  // $b is a soft copy of $a, refcount++
$a = 11;  // $a changes, a new zval is created
而:

$a = 10;
$b = &$a; // $b is still a copy of a, but this time a reference
$a = 11;  // $a and $b change
那么在您的“示例6”中会发生什么呢?好吧,PHP知道refcount>1,但是您不能将$a的zval“软拷贝”到$c,因为否则当您更改$a或$b时,它也会更改$c的值,所以$c成为一个新的zval,refcount=1

$a = 10;    // new zval created (refcount=1)
$b = &$a;   // $b is a copy of $a but is_ref=1 (and refcount=2)
$c = $a;    // $c is a NEW zval, refcount=1

恐怕我没有很好地解释我自己:(如果你还有疑问,我可以再试一次。

如果你熟悉C语言,你必须从C语言的指针来思考。PHP中的变量是指向ZVAL的指针,所以当你“复制”时PHP中的一个变量,不是实际上复制了它的值,而是增加了refcount并复制了指针。但是,如果您更改了原始值,其他值也不会改变,因为PHP会执行一种称为“写时复制”的操作(除非refcount=1

$a = 10;
$b = $a;  // $b is a soft copy of $a, refcount++
$a = 11;  // $a changes, a new zval is created
而:

$a = 10;
$b = &$a; // $b is still a copy of a, but this time a reference
$a = 11;  // $a and $b change
那么在您的“示例6”中会发生什么呢?好吧,PHP知道refcount>1,但是您不能将$a的zval“软拷贝”到$c,因为否则当您更改$a或$b时,它也会更改$c的值,所以$c成为一个新的zval,refcount=1

$a = 10;    // new zval created (refcount=1)
$b = &$a;   // $b is a copy of $a but is_ref=1 (and refcount=2)
$c = $a;    // $c is a NEW zval, refcount=1

恐怕我没有解释清楚:(如果您仍有疑问,我可以再试一次。

我真的不明白您的问题,您能澄清您的疑问吗?请看两个示例中的
示例3
示例4
,但为什么
示例6
中的总和与第三个和第四个示例中的总和不同?我真的不明白您的问题,您能澄清一下吗您的疑问?请看两个示例中的
示例3
示例4
,但是为什么在
示例6
中没有像第三个和第四个示例中那样求和?我不太理解您的解释,很抱歉,我不明白为什么要创建新的zval容器?因为变量$a和$b variable是硬链接吗?是的,对不起,明天我会再试一次,我意识到这一点并不清楚。问题恰恰是$a和$b是硬链接。这一事实迫使你在做$c=$b时进行深度复制,因为如果你只是增加引用计数,那么你必须检查所有硬拷贝,并在更改$c或$b时对它们进行全部更改$a/$bI不太理解您的解释,很抱歉,我不明白为什么要创建一个新的zval容器?因为变量$a和$b是硬链接?是的,对不起,明天我会再试一次,我意识到这一点不清楚。问题恰恰是$a和$b是硬链接。这一事实迫使您进行深入的分析在执行$c=$b时复制,因为如果只是增加refcount,那么在更改$c或$a/$b时,您必须检查所有硬拷贝并将其全部更改