复制带有引用的数组;如何仅获取值


Copying an array with references; how to get the values only

当我遇到一个有趣的问题时,我正在弄乱数组和引用。 以以下代码为例:

// Set everything up
$testArray = array(
    'a' => array(),
    'b' => array()
);
$saved = array();
$ref =& $testArray['b'];
// Set a value via the reference
$ref = array(1);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?
// Set another value via the reference
$ref = array(2);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?

没什么太复杂的。 它创建一个数组,并引用数组中的"深层值"。

当我var_dump($saved)时,结果不是我所期望的! 我得到:

array(2) {
  [0]=>
  array(2) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    &array(1) {
      [0]=>
      int(2)
    }
  }
  [1]=>
  array(2) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    &array(1) {
      [0]=>
      int(2)
    }
  }
}

我认为数组是按值而不是引用复制的。 为什么[b]在两个地方都等于array(2)? 如何复制数组并中断其引用?

我希望结果是:

array(2) {
  [0]=>
  array(2) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    array(1) {
      [0]=>
      int(1)
    }
  }
  [1]=>
  array(2) {
    ["a"]=>
    array(0) {
    }
    ["b"]=>
    array(1) {
      [0]=>
      int(2)
    }
  }
}

为什么$ref仍然链接到$testArray数组的副本? 我想基本上保存数组的"状态",并且让引用只更新原始而不是副本。

你的数组包含数组的引用,如果你复制你的数组,子数组只是引用......您需要一个深副本。创建一个递归函数:

function cloneArray($array){
    $newArray = array();
    foreach($array as $key => $value){
        if(is_array($value))
            $value = cloneArray($value);
        $newArray[$key] = $value;
    }
    return $newArray;
}

这应该适合您的需求

这是

预期行为。您可以使用函数debug_zval_dump()查看索引b的引用计数器确实是2

// Set everything up
$testArray = array(
    'a' => array(),
    'b' => array()
);
$saved = array();
$ref =& $testArray['b'];
// Set a value via the reference
$ref = array(1);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?
debug_zval_dump($saved[0]);
// Set another value via the reference
$ref = array(2);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?

什么给你:

array(2) refcount(3){
  ["a"]=>
  array(0) refcount(1){
  }
  ["b"]=>
  &array(1) refcount(2){
    [0]=>
    long(1) refcount(1)
  }
}

如果你想规避这种行为,你需要取消设置引用并在修改它之前获取一个新的引用:

// Set everything up
$testArray = array(
    'a' => array(),
    'b' => array()
);
$saved = array();
$ref =& $testArray['b'];
// Set a value via the reference
$ref = array(1);
unset($ref);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?
debug_zval_dump($saved[0]);
$ref =& $testArray['b'];
// Set another value via the reference
$ref = array(2);
unset($ref);
// Save the current array state
$saved[] = $testArray; // This shouldn't be a reference, right?
var_dump($saved);

然而,这只是理论上的东西。当然,您可以在不使用引用的情况下更轻松地完成此操作。