我有一个功能:
$query = "SELECT * from lol";
database_query( $query );
考虑到$query
永远不会在database_query函数内部进行更改,使用指向$query
的指针是一种好习惯,因此该函数不需要为新的迭代分配更多的内存。传入的价值?
function database_query( &$query ){
//do stuff that does not affect $query
}
答案 0 :(得分:6)
不,不要这样做。如果在函数("copy on write")内部更改了非传递引用参数的值,PHP将仅创建该字符串的另一个副本。没有理由通过将参数作为参考来让人们阅读您的代码错误的印象。
答案 1 :(得分:1)
$query
的值是一个字符串。字符串没有内部可变状态 - 在PHP中“更改”包含字符串的变量的唯一方法是为其分配一个新字符串(或通过引用将其传递给函数,然后该函数为其分配一个新字符串等)。因此,当您执行$foo = $query;
时,任何合理的实现都只是将指针复制到内部字符数组,而不是复制实际字符,因为它们无法更改。因此,即使您不知道PHP具有写入时复制,您也可以得出结论,按值传递字符串并不昂贵。
答案 2 :(得分:-2)
这是一个非常有趣的问题,我花了最后一个半小时阅读关于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的引用[&#39; a&#39;]。
当我调用noref_write函数时,我们看到refcount降为1(如果你看看PHP的内置函数,则为2)。为什么?因为这是&#34;复制写入&#34;问题发生了。直到我们增加$ var_a PHP在内部使用$ var_a作为对$ a的引用但是当我们更改了值时,我们强制PHP生成变量的副本,以便它可以递增。所以在这一点上,$ var_a不再是对$ a的引用,而是改为引用它自己的数据。
ref_nowrite函数显示不明确的结果。单单看它我们无法证明什么。然而,ref_write函数告诉我们XDebug说我们正在处理一个引用变量(is_ref = 1),最重要的是我们看到在我们增加$ var_a后,我们的全局变量$ a的值也发生了变化 - 这意味着$ var_a和$ GLOBALS [&#39; a&#39;]肯定指向内存中的相同位置。这意味着更改$ var_a并不会触发写入&#34;副本#34;情况 - 因为我们正在处理参考资料,所以不应该这样做。
玩弄这个以说服自己,并在这里阅读更多内容:
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