php - PHP Copy on Write 在 Arrays 与 Objects

我有一个关于PHP 中的copy one write optimization 的问题,我认为它与https://stackoverflow.com/questions/11074970/will-copy-on-write-prevent-data-duplication-on-arrays 不同,并且这个问题标记为https://stackoverflow.com/questions/66703161/does-phps-copy-on-write-work-with-arrayshttps://stackoverflow.com/questions/628938/what-is-copy-on-write 我也觉得这里没有解决这个问题。

在我的观察中,copy on write 优化似乎与 arrays 和 objects 的工作方式不同。使用 arrays,似乎如果有任何变化,无论数组的深度如何,都会发生副本。对于objects,似乎copy on write 只看浅层。

考虑:

class B{
  var $b;
  function __construct($x) { $this->b = $x; }
}

$w = [new B(0)];
$x = $w; // $x references $w 
$x[0]->b = 1; // now $x does not reference $w 

$y = new B(0);
$z = $y; // $z references $y 
$z->b = 1; // $z still references $y

我根据将 $w、$x、$y 和 $z 传递给 debug_zval_dump 函数来确认这些引用。

有人可以解释为什么会这样吗?我提供的第二个链接中的答案提到“只要没有更改单个字节”,也许这就是我需要更好地理解的内容。我对 PHP objects 的心智模型一直是它们是有效的指针。并且 "$x[0]->b = 1" 中指向 B 的指针没有改变,所以我认为这不是单个字节的改变。

我也不明白为什么在这方面 objects 的行为与 arrays 不同。

除了必须阅读或发布在 Stack Overflow 上之外,这种行为是否被正确记录在了某个地方? PHP.net 手册对于该语言的更多理论细节毫无帮助。例如,使用 JavaScript,可以查看 ECMAScript 标准。 PHP 似乎不存在这种情况。

回答1

您可以简单地使用 var_dump() 来查看 object ID,而不是尝试根据 refcount 进行推断。

例如:

class B{
  var $b;
  function __construct($x) { $this->b = $x; }
}

$w = [new B(0)];
$x = $w;
$x[0]->b = 1;

var_dump($w, $x);

$y = new B(0);
$z = $y;
$z->b = 1;

var_dump($y, $z);

输出:

array(1) {
  [0]=>
  object(B)#1 (1) {
    ["b"]=>
    int(1)
  }
}
array(1) {
  [0]=>
  object(B)#1 (1) {
    ["b"]=>
    int(1)
  }
}

object(B)#2 (1) {
  ["b"]=>
  int(1)
}
object(B)#2 (1) {
  ["b"]=>
  int(1)
}

在这里我们可以看到 object(B)#1 是通过数组赋值保留的。