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 に答える