事实证明这是一个非常有趣的问题,我在过去的一个半小时里阅读了有关 PHP 以及它如何处理引用的信息(感谢 Tim Cooper 提供的链接让我开始学习)。
要回答您的问题,是的 - 在调用函数时使用这样的引用是一种很好的做法。通过使用引用,您将使用更少的资源 - 引用变量没有“写入时复制”。这里有一些证据:
<?php
function noref_nowrite($var_a){
echo '<h3>NOT Using a Reference/Not Changing Data</h3>';
echo '<p>'. xdebug_debug_zval('var_a') .'</p>';
echo '<p>'. debug_zval_dump($var_a) .'</p>';
echo '<p>$var_a = '. $var_a .' and $GLOBALS[a] = '. $GLOBALS['a'] .'</p>';
}
function noref_write($var_a){
$var_a++;
echo '<h3>NOT Using a Reference/Changing Data</h3>';
echo '<p>'. xdebug_debug_zval('var_a') .'</p>';
echo '<p>'. debug_zval_dump($var_a) .'</p>';
echo '<p>$var_a = '. $var_a .' and $GLOBALS[a] = '. $GLOBALS['a'] .'</p>';
}
function ref_nowrite(&$var_a){
echo '<h3>Using a Reference/Not Changing Data</h3>';
echo '<p>'. xdebug_debug_zval('var_a') .'</p>';
echo '<p>'. debug_zval_dump($var_a) .'</p>';
echo '<p>$var_a = '. $var_a .' and $GLOBALS[a] = '. $GLOBALS['a'] .'</p>';
}
function ref_write(&$var_a){
$var_a++;
echo '<h3>Using a Reference/Changing Data</h3>';
echo '<p>'. xdebug_debug_zval('var_a') .'</p>';
echo '<p>'. debug_zval_dump($var_a) .'</p>';
echo '<p>$var_a = '. $var_a .' and $GLOBALS[a] = '. $GLOBALS['a'] .'</p>';
}
$a = 5;
noref_nowrite($a);
noref_write($a);
ref_nowrite($a);
ref_write($a);
?>
如果您将上述代码复制/粘贴到 PHP 页面并执行它,您将看到:
NOT Using a Reference/Not Changing Data
var_a: (refcount=3, is_ref=0)=5
long(5) refcount(4)
$var_a = 5 and $GLOBALS[a] = 5
NOT Using a Reference/Changing Data
var_a: (refcount=1, is_ref=0)=6
long(6) refcount(2)
$var_a = 6 and $GLOBALS[a] = 5
Using a Reference/Not Changing Data
var_a: (refcount=3, is_ref=1)=5
long(5) refcount(1)
$var_a = 5 and $GLOBALS[a] = 5
Using a Reference/Changing Data
var_a: (refcount=3, is_ref=1)=6
long(6) refcount(1)
$var_a = 6 and $GLOBALS[a] = 6
所以我们这里有四个基本测试。我创建了一个全局变量 ($a) 并将其赋值为 5。
当我调用 noref_nowrite 函数时,我们看到 XDebug 计数为 3 个引用,而 PHP 的内置函数计数为 4。有趣的是,PHP 在内部对此进行了优化,因此它实际上就像调用 ref_nowrite 函数一样,因为 PHP 使 $var_a 成为对 $GLOBALS[' 的引用a']。
当我调用 noref_write 函数时,我们看到 refcount 下降到 1(如果您查看 PHP 的内置函数,则下降到 2)。为什么?因为这是发生“写时复制”问题的地方。在我们增加 $var_a 之前,PHP 在内部使用 $var_a 作为对 $a 的引用,但是当我们更改值时,我们强制 PHP 复制变量以便它可以增加。所以此时 $var_a 不再是对 $a 的引用,而是改为引用它自己的数据。
ref_nowrite 函数显示不明确的结果。单看它,我们无法证明任何事情。然而 ref_write 函数告诉我们 XDebug 说我们正在处理一个引用变量(is_ref=1),最重要的是我们看到在我们增加 $var_a 之后,我们的全局变量 $a 的值也发生了变化——这意味着 $var_a 和$GLOBALS['a'] 肯定指向内存中的同一个地方。这意味着更改 $var_a 不会触发“写入时复制”的情况 - 并且不应该因为我们正在处理引用。
玩弄这个来说服自己,这里还有一些阅读:
Detecting whether a PHP variable is a reference / referenced(我认为 ircmaxell 有一个深思熟虑的答案)
http://us2.php.net/debug-zval-dump
XDebug 文档:http://xdebug.org/docs/display
PHP 引用的作用:http://us3.php.net/manual/en/language.references.whatdo.php
PHP 引用计数基础知识:http://us3.php.net/manual/en/features.gc.refcounting-basics.php