通过引用传递如何或为什么用PHP覆盖其他引用?
有人能给我解释一下为什么引用变量传递会以我所看到的方式进行 以下是我正在处理的控制器的一个方法:通过引用传递如何或为什么用PHP覆盖其他引用?,php,pass-by-reference,byref,Php,Pass By Reference,Byref,有人能给我解释一下为什么引用变量传递会以我所看到的方式进行 以下是我正在处理的控制器的一个方法: public function view($view,$context=array()){ // <snip> foreach($context as $a=>$b){ $$a = $b; } // <snip> } 作为一个有点大惊小怪的人,我想处理实际的对象而不是副本(这看起来很浪费),所以我将其改为: public
public function view($view,$context=array()){
// <snip>
foreach($context as $a=>$b){
$$a = $b;
}
// <snip>
}
作为一个有点大惊小怪的人,我想处理实际的对象而不是副本(这看起来很浪费),所以我将其改为:
public function view($view,$context=array()){
// <snip>
foreach($context as $a=>$b){
$$a =& $b;
}
// <snip>
}
在测试用例中,两个对象被传递到视图,然后视图输出相关数据。当通过引用而不是通过值传递时,这两个变量都以对第二个对象的引用结束
我没想到会发生这种事。我非常希望有人向我解释为什么会发生这种情况。我可能错过了一些明显的东西,所以请教育我
以防相关(我怀疑可能相关,但我不确定)
该方法的调用方式如下:
$data = array();
$data['foo'] =& $this->module()->get_foo();
$data['bar'] =& $this->module()->get_bar();
$this->view('nameOfView',$data);
在这个实例中,通过引用获取返回,因此这里的&可能有些过分。再说一次,我没有我想的那么确定。出于这个问题的目的,我真的很想了解视图方法中引用覆盖的情况,但请随意教我其他我应该知道但显然不知道的内容。因为变量
$b
正在被foreach
循环重用。当
$b
被重新分配时,所有对它的引用都会被重新分配
简单的例子:
$a = [1, 2, 3];
$c = [];
foreach($a as $b)
{
$c[] = &$b;
}
print_r($c);
这将产生:
Array
(
[0] => 3
[1] => 3
[2] => 3
)
您甚至可以更进一步,在foreach
循环之后执行作业:
$b = 'derp';
这将使您的阵列变成:
Array
(
[0] => derp
[1] => derp
[2] => derp
)
现在,正如我在评论中两次提到的,有一个函数叫做,它似乎完全是为了你想做的事情而做的,这就是我建议的方法
但为了完整性起见,“修复”代码相当简单。有两种方法可以做到这一点:
- 将
作为参考而不是副本。$b
您可以使用
作为$a as&$b
的参数来实现这一点:foreach
$a = [1, 2, 3]; $c = []; foreach($a as &$b) { $c[] = &$b; } print_r($c);
- 在重新分配之前,中断对
的引用。$b
您可以通过调用unset($b)来实现这一点代码>在循环结束时:
$a = [1, 2, 3]; $c = []; foreach($a as $b) { $c[] = &$b; unset($b); } print_r($c);
Array
(
[0] => 1
[1] => 2
[2] => 3
)
请注意,当使用第一种方法并在此之后修改$a
时,$c
也可能会更改,但并不总是如此。例如,直接赋值(
$a[0]=5;
)将影响$c
($c[0]=5
)。$c
不受$a
上任何其他操作的影响(据我所知),但在弄乱了$a
中的索引后(与数组移位()
或洗牌()
一样,$c[1]
可能是对$a[0]
的引用,等等
如果您不想头痛,只需使用
extract()
我现在无法详细解释,但一般来说,使用foreach循环变量的引用会带来麻烦。但请注意,不会复制对象。如果有一个对象数组,则会复制该数组本身,包括对对象的引用,但对象本身仍然是原始对象,因此优化是无用的。我认为在你的第二个循环中,你正在用对迭代中最后一个对象的引用替换数组中的所有项。我只是读到了“作为一个小题大做的人,我想处理实际对象而不是副本”。两个观察结果:a)和b)(即,当您分配$$a=$b时,您没有在处理实例的副本)-也许这使您的问题成为一个非问题(尽管可能很有趣)。我过去也是一个大惊小怪的人,担心过度复制。但后来我了解到,“拷贝”是“惰性拷贝”,这意味着只有当您实际修改数据的“拷贝”时,才会进行拷贝。在此之前,您正在读取内存中相同的数据(在大多数情况下,我发现我很少修改输入参数)。这与您的函数不一样吗?对引用的解释都有//第二点
,就是foreach中只有一个变量$b
,它的值改变了,对它的引用没有改变。PHP引用可以是“有趣的”-/这是一个可靠的答案。我知道现在发生了什么,是的,确实会使用extract.being'picky'-只有一个变量$b,所以一切都指向它。它包含foreach
循环的最后一个值。@RyanVincent,但有多个变量,每个变量在某个点被称为$b
:pforeach
循环变量可以保存对“循环对象”的引用参见foreach($a as和$b)
-注意和$b
。唉,这在这里没有发生。发生的情况是引用了循环变量$b
。因此,每个人都可以引用“循环变量”,而不是它所指向的对象!。因此,每个人都会看到“循环变量-$b”的最后一个值。这是循环中的最后一个值。
$a = [1, 2, 3];
$c = [];
foreach($a as $b)
{
$c[] = &$b;
unset($b);
}
print_r($c);
Array
(
[0] => 1
[1] => 2
[2] => 3
)