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?

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

4

2 回答 2

2

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

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

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

        $newArray[$key] = $value;
    }

    return $newArray;
}

这应该可以满足您的需求

于 2013-09-16T21:21:46.717 回答
1

这是预期的行为。您可以使用该函数debug_zval_dump()查看索引的 refcounter 确实b2.

// 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);

然而,这只是理论上的东西。您当然可以更轻松地完全不使用引用。

于 2013-09-16T20:47:22.840 回答