PHP:递归调用之间共享引用

时间:2011-11-26 23:13:51

标签: php recursion reference pass-by-reference

我有三个函数,foobarbaz,从我的角度来看,它应该产生相同的结果。但是,我遇到了在递归函数调用之间引用共享的问题。

$array = array(
    'subs' => array(
        'a' => 1,
        'b' => 2,
    ),
);

function foo(&$array, $value, $callAgain = true) {
    $subs =& $array['subs'];
    foreach ($subs as &$sub)
        $sub = $value;
    if ($callAgain) {
        $copy = $array;
        foo($copy, $value + 1, false);
    }
}

function bar(&$array, $value, $callAgain = true) {
    foreach ($array['subs'] as &$sub)
        $sub = $value;
    if ($callAgain) {
        $copy = $array;
        bar($copy, $value + 1, false);
    }
}

function baz(&$array, $value, $callAgain = true) {
    foreach ($array['subs'] as $key => $sub)
        $array['subs'][$key] = $value;
    if ($callAgain) {
        $copy = $array;
        baz($copy, $value + 1, false);
    }
}

foo($array, 3);
var_dump($array);
bar($array, 3);
var_dump($array);
baz($array, 3);
var_dump($array);

此代码产生以下结果:

array
  'subs' => 
    array
      'a' => int 4
      'b' => int 4
array
  'subs' => 
    array
      'a' => int 3
      'b' => int 4
array
  'subs' => 
    array
      'a' => int 3
      'b' => int 3

但是,我希望所有这些都返回3, 3,因为数组的副本会传递给递归调用。

如何修复前两个函数以使它们返回3, 3?我不想使用baz函数的语法,因为它非常详细。

1 个答案:

答案 0 :(得分:3)

我认为你已经回答了自己的问题 - baz是获得你想要的行为的方法。其他两个函数的行为与PHP中的预期一致,至少根据What References Do上的手册页:

  

但请注意,数组内部的引用可能存在危险。使用右侧的引用执行正常(非引用)赋值不会将左侧转换为引用,但是在这些正常赋值中保留数组内的引用。这也适用于通过值传递数组的函数调用。例:       

/* Assignment of array variables */
$arr = array(1);
$a =& $arr[0]; //$a and $arr[0] are in the same reference set
$arr2 = $arr; //not an assignment-by-reference!
$arr2[0]++;
/* $a == 2, $arr == array(2) */
/* The contents of $arr are changed even though it's not a reference! */
?>
  

换句话说,数组的引用行为是逐个元素定义的;单个元素的引用行为与数组容器的引用状态分离。