PHP: $var 和 &$var 有啥区别?

Posted

技术标签:

【中文标题】PHP: $var 和 &$var 有啥区别?【英文标题】:Php: what's the difference between $var and &$var?PHP: $var 和 &$var 有什么区别? 【发布时间】:2011-06-01 02:44:09 【问题描述】:

有什么区别

foreach ($my_array as $my_value) 

还有:

foreach ($my_array as &$my_value) 

?

我可以请你给我两个真实的例子,说明什么时候使用一个,什么时候使用另一个?

【问题讨论】:

根据经验,永远不要使用引用。 @troelskn:这是一条愚蠢的经验法则。有时你必须使用它们。如果您不知道是否应该使用它们,那么您可能不必这样做。但是每当你想修改实际值时,你必须使用引用。 @Felix Kling:我同意@troelskn。我从来不需要修改数组的实际值。每次我不得不这样做时,您都可以编写比使用 ('&$var') 更好的代码。我能想到的唯一方法可能是......优化:如果您使用'&',我想(如果我错了,请纠正我)没有必要将副本复制到临时变量中。从而获得执行时间。如果您有一个示例无法避免像我的问题中带有“&”的循环,我可以请您在此处将它们显示为评论吗?非常感谢! @oliver 实际上,由于 php 的内部机制,在大多数情况下使用引用会更慢 @felix 我的意思是,如果您需要参考来做您想做的事,那么您做错了什么。重构你的代码。 【参考方案1】:

第一个示例创建值的副本,而第二个示例使用对原始值的引用。所以在第一个foreach 运行之后,原始数组仍然保持不变。在第二个foreach 之后,原始数组可能已被修改,因为它是通过引用处理的。

一些原生 PHP 函数已经以这种方式工作,例如 shuffle(),它会重新排列数组的内容。你会注意到这个函数不返回一个数组,你只是调用它:

$myArray = array('foo', 'bar', 'fizz', 'buzz');
shuffle( $myArray );
// $myArray is now shuffled

它发挥了它的魔力,因为它通过引用而不是创建它的副本来处理数组。

还有一些函数不通过引用传递任何东西,而是处理原始值的副本,例如ucwords(),它返回新的结果字符串:

$myString = "hello world";
$myString = ucwords( $myString );
// $myString is now capitalized

见Passing by Reference。

【讨论】:

如果 $my_value 是一个对象,它必然是通过引用传递的。 @Epharion:不,PHP 总是通过 val 传递,除非它被告知传递 ref。对象也不例外。由于 PHP 存储对象的方式,仅对于对象,val 传递与 ref 传递非常相似;)【参考方案2】:

Jonathan's answers 描述得很好。为了完整起见,这里是您的两个示例:

    只是读取值:

    $my_array = range(0,3);
    foreach ($my_array as $my_value) 
        echo $my_value . PHP_EOL;
    
    

    为每个元素添加一些数字(因此修改每个值):

    foreach ($my_array as &$my_value) 
        $my_value += 42;
    
    

    如果您不使用&$my_value,则添加不会对$my_array 产生任何影响。 但是你可以不使用引用来编写相同的内容:

    foreach($my_array as $key=>$value) 
        $my_array[$key] = $value + 42;
    
    

    不同之处在于我们直接使用$my_array[$key]访问/更改原始值。

DEMO

【讨论】:

【参考方案3】:

当您在变量前加上 & 符号时,您正在创建一个“引用”。 PHP 引用就像您计算机上的快捷方式或符号链接。您可以创建一个指针变量,它只是相同数据的另一个名称。

我没有看到使用这些有很大的不同,除了你不要复制一个变量来节省内存。当您传递变量时,您可以将引用和引用点传递给原始对象。

【讨论】:

一个典型的初学者错误:认为 PHP 是愚蠢的。 PHP 不会盲目地复制值。它使用写时复制的概念,即仅在更改值时复制该值。出于性能原因创建引用通常只会适得其反,因为它通常会导致 PHP 只进行更多的复制。【参考方案4】:

& 使用的真实示例是当您需要用很少的代码行更改数组的内容时

foreach($arrFeed as &$objFeed)
  $objFeed['externalSrc'] = convertToLocalImage($objFeed['externalSrc']);

【讨论】:

【参考方案5】:

当我必须阅读 csv 文件以了解分隔符是什么时,我只使用引用。只取第一行:

$handle = fopen($file, "r");
$firstLine = fgets($handle);
fclose($handle);

然后用这个可能的分隔符

$delimiters = array(';' => 0,',' => 0,"\t" => 0,"|" => 0);

通过引用计数最常用的内容

foreach ($delimiters as $delimiter => &$count) 
    $count = count(str_getcsv($firstLine, $delimiter));

$delimiter =  array_search(max($delimiters), $delimiters);

【讨论】:

以上是关于PHP: $var 和 &$var 有啥区别?的主要内容,如果未能解决你的问题,请参考以下文章

为啥不使用嵌套的 if 语句有啥具体原因吗? [关闭]

在 PHP 中,差异是啥: $var2=$var1 ; $var2=&$var1; [复制]

$(var) 和 var 有啥区别?

彩色 var_dump() 和错误

Bash shell 中的 $var、"$var" 和 "$var" 有啥区别?

这个 php 行有啥问题?