这不仅仅是关于 Smarty,我想大多数模板引擎都分配了变量。这更像是一个理论问题,而不是实际问题。我没有用例。
当您将一个大数组 $a
分配给另一个变量 $b
时,PHP 会发生什么? PHP复制数组?也许,只是也许,它在内部创建了一个指针。那么当你稍微改变 $a
时会发生什么? $b
不应更改,因为没有使用 &
来创建 $b
。 PHP 只是将内存使用量加倍吗??
更具体地说:当您将一个大数组从 Controller ($a
) 分配给您的模板引擎 ($tpl->vars['a']
) 并在 View 中使用(extract
到 $a
)? PHP 的内存只是增加了三倍吗??
现在如果我通过引用分配所有变量会发生什么?我很高兴我的观点能够将数组改回 Controller (无论如何我都不会回到那里)。如果变量在模板引擎 ($tpl->vars['a']
) 中发生变化也没有问题。
通过引用分配所有变量是否更利于内存?性能更好?如果是这样:是否有可能出现奇怪的、不需要的副作用?
因为人们喜欢代码而不是故事:
// copies
$a = array( ... );
$tpl->assign('a', $a); // creates a copy (?) in $tpl->vars['a']
// pointer / by ref
$a = array( ... );
$tpl->assign_by_ref('a', $a); // creates a pointer in $tpl->vars['a'] because:
function assign_by_ref( $name, &$var ) {
$this->vars[$name] = $var; // voila pointer?
}
我很确定 PHP 不介意大数组、副本和克隆,但在性能和内存方面:哪个“更好”?
编辑
对于对象,所有这些都无关紧要。对象总是通过引用自动分配。由于物体很热,也许这是一个过时的问题,但我很好奇。
更新
所以 PHP 使用 copy on write
... 喜欢它。对象总是指针。当您:
$a = new BigObject;
$b = $a; // pointer, right?
$b->updateSomethingInternally(); // $b is now changed > what about $a?
这是否触发了写时复制?还是 $a 和 $b 仍然相同(如 ===
)?
编辑
我可以得出结论,仅仅为了节省内存,通过 ref 分配真的不值得吗? PHP 本身是否足够智能?
编辑
复制、克隆、引用等的有趣可视化:http://www.phpinsider.com/download/PHP5RefsExplained.pdf
最佳答案
PHP 使用一种称为写时复制的概念。 IE。如果您只是执行 $a = $b
,PHP 不会将 $b
的整个值复制到 $a
。它只会创建某种指针。 (更准确地说,$a
和 $b
将指向相同的 zval,并且它的 refcount
将增加。)
现在,如果 $a
或 $b
被修改,则该值显然不能再共享,必须复制。
因此,除非您不在模板代码中修改数组,否则不会进行任何复制。
一些进一步的说明:
谨防通过盲目插入引用来优化您的代码。通常它们会产生与您预期相反的效果。解释原因的示例:
$a = SOMETHING_BIG; // $a points to a zval with refcount 1 and is_ref 0 $b = $a; // $a and $b both point to a zval with refcount 2 and is_ref 0 $c =& $a; // Now we have a problem: $c can't just point to the same zval // anymore, because that zval has is_ref to 0, but we need one // with is_ref 1. So The zval gets copied. You now have $b // pointing to one zval with refcount 1 and is_ref 0 and $a and // $c pointing to another one with refcount 2 and is_ref 1
所以与你想要的相反的事情发生了。您实际上不是在节省内存,而是在分配额外的内存。通常很难判断添加引用会使它变得更好还是更坏,因为通常很难跟踪指向一个 zval 的所有不同变量(它通常不像看起来那么容易,只要看看
debug_zval_dump
的示例)功能。因此,真正了解引用是否对性能有益的唯一安全方法是实际分析这两种变体。- 在 PHP 中,对象与其他所有内容一样按值传递。仍然你是对的,它们的行为像,因为对于对象,传递的这个值只是指向其他数据结构的指针。在大多数情况下,按引用传递和类似引用的行为之间的区别并不重要,但仍然存在差异。
这只是对该主题的简短介绍。您可以在 blog post by Sara Golemon with the porvoking title "You're being lied to" 中找到对该主题的更深入分析。 .
关于php - Smarty(和其他 tpl ngins): assign and assign_by_ref,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5794746/