使用引用复制数组;如何只获取值

时间:2013-09-16 20:38:15

标签: php arrays reference

当我遇到一个有趣的问题时,我正在搞乱数组和引用。拿这个代码,例如:

// 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数组的副本?我想基本上保存数组的“状态”,并且引用只更新原始而不是副本。

2 个答案:

答案 0 :(得分:2)

您的数组包含数组的引用,如果复制数组,子数组只是引用...您需要深层复制。做一个递归函数:

function cloneArray($array){
    $newArray = array();

    foreach($array as $key => $value){
        if(is_array($value))
            $value = cloneArray($value);

        $newArray[$key] = $value;
    }

    return $newArray;
}

这应该可以满足您的需求

答案 1 :(得分:1)

这是预期的行为。您可以使用函数debug_zval_dump()来确定索引b的refcounter确实是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);

然而,这只是理论上的东西。你可以在不使用参考文献的情况下轻松完成。