PHP传递引用还是值 - 问题

4

我打算向我们的实习生解释PHP中“按引用传递”和“按值传递”的区别,然后写了这个简单的脚本:

$a=5; 
$b=&$a; 
$a=8; 
echo $b;
// prints  8
$a=5; 
$b=$a;  //no &
$a=8; 
echo $b;
// prints 5

然而,使用php-cli运行php -qa会产生以下结果:
php >     $a=5; 
php >     $b=&$a; 
php >     $a=8; 
php >     echo $b;
8
php >     // prints  8
php >     $a=5; 
php >     $b=$a;  //no &
php >     $a=8; 
php >     echo $b;
8
php >     // prints 5

在IT技术中,$b=$a;这段代码不应该解除 $a 和 $b 的链接关系吗?

因此我变得好奇,并尝试了以下操作:

php > $b=3;
php > echo $a;
3

那么,我错在哪里了?发生了什么?看起来设置引用的操作似乎一直保持着,尽管在$b=$a这行应该已经清除了引用。我也尝试过:

php >    $e=5; $f=$e; $e=6; echo $f; 
5

...这一切都像预期的那样工作。

$a$b似乎永久地链接在一起?我是否漏掉了什么重要的点?如何“取消链接”$a$b变量?


你在第二部分之前尝试过 unset($b) 吗? - Aleks G
如果你没有明确的意思,请不要在同一作用域内重复使用变量名。 - hakre
3
+1 是因为这个问题展示了试着向新手解释某件事情如何能够帮助你更好地理解它。 - Arkh
6个回答

6

如果将一个值分配给变量,为什么应该清除引用?其工作方式如下(带有半简化的注释):

$a = 5;    // creates a "slot", puts 5 in it, makes $a point to it
$b =& $a;  // makes $b point to the same "slot" $a points to
$c = 6;    // creates a "slot", puts 6 in it, makes $c point to it
$a = $c;   // puts the value of the slot $c points to into the slot $a points to
echo $b;   // outputs the value of the slot $b points to (6)

这是将一个分配给一个变量。无论该值是文字5)还是另一个变量保存的都没有关系。该引用会一直存在,直到您使用unset($b)取消该变量。


非常感谢您在这里留下的许多评论 :) 您的解释非常好,deceze。我曾经(显然是错误的)认为$b=$a会为$b创建一个新的槽,并复制$a的值,但现在我明白了,那可能会非常低效。无论如何,还是非常感谢! Jonas - jonasfh
@user 效率并不是问题,而是这才是逻辑上应该的工作方式。 - deceze

1

好的,是的,因为你将 $b 创建为对 $a 的引用。所以,在该行上执行的操作是:

$b = $a

只是将 5 赋值给 $a,因为 $b 仍然引用 $a

如果您想要“取消引用”,则必须使用 unset 并重新创建变量。


0

也许使用更具表意的变量名可以使您更清晰地了解:

$value = 5; 
$alias = &$value; 
$value = 8;
echo $alias;   # 8
$value = 5; 
$alias = $value; # no &
$value = 8;
echo $alias;   # 8 (OP expected 5)

这样阅读起来更容易,对吧?

特别注意这一行:

$alias = $value; # no &

这里发生了什么?
由于$alias$value的别名,所以你基本上是在写:
$value = $value;

此时的值为5。

然后您将$value设置为8。

$alias仍然是指向$value的。

如果您想要停止$alias成为$value的别名,则可以将其转换为指向其他内容的别名:

$alias = &$other;

或者只需取消引用:

unset($alias);

0

当你的代码第一次使用 $b 时,它会创建变量 $b 并将其链接到 $a 的位置。随后,您将向共享位置写入值。您无法撤消变量引用的位置。


0
跟进我的评论...我运行了你的脚本 - 在两种情况下都输出了'8'。我在第一个echo后添加了unset($b)并再次运行 - 现在输出是85,如预期。

0
问题在于当你执行$b = $a时,由于$b是$a的引用,实际上你正在执行$a = $a。正如其他人所说,你需要执行unset($b)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接