PHP函数数组参数通过引用

时间:2013-01-14 20:27:54

标签: php arrays function reference

为什么这段代码不能像我预期的那样工作? 在Test(& $ array)函数内部,我将ref参数设置为全局$ array1,但这不起作用。

$array1 = array();
$array2 = array();

function Test(&$array)
{
    global    $array1;
    $array = &$array1;

    $array['inside'] = 'inside';

}

//按功能设定:

Test($array2); 
$array2['test1'] = 'test1';

var_dump($array1); //array('inside' => 'inside') ** WHERE IS THE 'test1'  key? **
var_dump($array2); //array('test1' => 'test1')   ** WHERE IS THE 'inside' key? **

//没有功能的设置:

$array2 = &$array1;
$array2['test2'] = 'test2';

var_dump($array1); //array('inside' => 'inside', 'test2' => 'test2') ** FINE **
var_dump($array2); //array('inside' => 'inside', 'test2' => 'test2') ** FINE **

编辑:

很明显,如果我将$ array更改为指向$ array1,那么$ array1将具有'inside'=> “内部”值 外部 该功能。有什么不清楚,如果我设置$ array2 ['test1'] ='test1'为什么不更改此$ array1 ?它在函数内部'链接'!

2 个答案:

答案 0 :(得分:5)

在函数内部执行$array = &$array1;时,您正在更改局部变量$array的值。

它过去曾引用$array2,但现在它包含对$array1的引用。因此,当您修改$array时,您正在修改$array1

答案 1 :(得分:2)

这是我对PHP中引用的理解,以及为什么代码没有达到预期的效果(如果我弄错了,有人请抓我,我经常使用引用!另外,我确信有更好的术语比我称之为“标识符”和“价值”;我只是想避免在任何一个概念中使用“变量”。)

  • 有一堆变量标识符(您获取数据的方式)和一堆变量值(实际上是数据)
  • 对于普通变量,只有一个标识符指向一个值。例如$foo指的是一个特定的值 - PHP内部的一个存储桶,可以容纳一个数字,一个字符串等。
  • 每次使用普通赋值运算符时,例如$foo = 42,PHP查找指向的值并更新它 - 因此标识符$foo没有改变,但它指向的值有。
  • 分配参考时,例如$bar =& $foo,您实际上是在告诉PHP更改标识符本身。所以现在$bar$foo是指向相同值的两个不同的标识符。 $foo = -1$bar = -2都会写入此值,无论您给出的是哪个名称,都指的是该值。
  • 到目前为止,这么好。但是,如果我现在写$foo =& $bob怎么办?由于我正在更改标识符,而不是$foo开始指向与$bob相同的值,但是$bar留在原处。现在,更改$foo不再对$bar产生任何影响。
  • 通过引用函数传入参数时会发生类似的事情。因此,在问题的示例中,行Test($array2)仍会在名为$array的函数内创建一个新的标识符,但它将其指向相同的$array2。但是,函数内部是行$array = &$array1,它接受​​新标识符($array)并将其指向与$array1相同的值。 $array2仍指向的旧值未发生变化。
  • 还有其他情况也是如此。例如,globalstatic关键字会创建一个指向现有值的额外标识符。如果您编写function foo() { global $foo; $bar = 2; $foo =& $bar; },则只更新函数的名为$foo的本地标识符,以指向$bar的值;全局标识符(当您处于全局范围时,也恰好称为$foo)仍然指向其原始值。

PHP中普通值的参考系统总是包含一个间接级别 - 例如,你不能以C语言的方式创建指向指针的指针。 / p>

唯一棘手的情况是对象,它在许多语言中都有自己的额外间接级别 - 而$foo = 42; $bar = $foo;42的值复制代表$foo的数据到$bar$foo = new stdClass; $bar = $foo复制对象指针。因此,虽然$foo$bar仍然具有单独的,但$foo = 42之类的作业对$bar不会产生任何影响,{{1 }}和$foo->a = 1;最终都会改变同一个对象。