3

我正在尝试克隆一个 \ArrayIterator 对象,但似乎克隆的对象仍在引用原始对象。

$list = new \ArrayIterator;
$list->append('a');
$list->append('b');

$list2 = clone $list;
$list2->append('c');
$list2->append('d');

// below result prints '4', i am expecting result '2'
echo $list->count();

有人对这种行为有解释吗?先感谢您。

4

2 回答 2

5

尽管我很难找到明确说明的文档,但内部保存数组ArrayIterator的私有$storage属性必须是对数组的引用,而不是直接存储在对象中的数组本身。

上的文档clone

PHP 5 将执行所有对象属性的浅拷贝。任何引用其他变量的属性都将保持引用。

因此,当您创建对象时,新克隆cloneArrayIterator对象包含对与原始对象相同的数组的引用。 这是一个旧的错误报告,其中这种行为被称为预期行为。

如果你想复制一个的当前状态,你可以考虑使用返回ArrayIterator的数组来实例化一个新的getArrayCopy()

$iter = new \ArrayIterator([1,2,3,4,5]);

// Copy out the array to instantiate a new one
$copy = new \ArrayIterator($iter->getArrayCopy());
// Modify it
$copy->append(6);

var_dump($iter); // unmodified
php > var_dump($iter);
class ArrayIterator#1 (1) {
  private $storage =>
  array(5) {
    [0] =>
    int(1)
    [1] =>
    int(2)
    [2] =>
    int(3)
    [3] =>
    int(4)
    [4] =>
    int(5)
  }
}

var_dump($copy); // modified
class ArrayIterator#2 (1) {
  private $storage =>
  array(6) {
    [0] =>
    int(1)
    [1] =>
    int(2)
    [2] =>
    int(3)
    [3] =>
    int(4)
    [4] =>
    int(5)
    [5] =>
    int(6)
  }
}

上面是一个简单的操作,只创建一个新ArrayIterator的,当前存储的数组作为原始数组。它不维护当前的迭代状态。为此,您还需要调用seek()以将指针推进到所需位置。这是一个详尽的答案,解释了如何做到这一点

于 2015-12-26T04:16:44.960 回答
1

完成之前所说的,如果你试图克隆一个继承自的类ArrayIterator,你可以使用这个方法来自动克隆存储的数组:

public function __clone(){
    parent::__construct($this->getArrayCopy());
}
于 2017-07-18T16:54:03.590 回答