PHP 4 对象是按值传递的,,除非用户通过添加 & 符号明确指定引用:&$variable。出于这个原因,可能会消耗大量内存的函数参数通过引用传递,以优化内存使用:
function f(&$huge) {
// ...
}
PHP 5 变量是通过引用传递的,即使用户没有明确指定它(不使用 & 字符)。通过将一个变量分配给另一个变量,我们只需为内存中的相同数据创建一个新容器(内部称为zval)。考虑一下:
$a = new stdClass;
$b = $a;
第一行为变量$a和stdClass的对象分配内存,并将对象的标识符存储到变量中。第二行为变量$b 分配内存,将对象的标识符存储到$b 变量中,并增加一个内部引用计数器。引用计数器值显示在代码中引用对象的次数。当$b 变量被销毁时,引用计数器减一。当引用计数器的值变为零时,对象的内存被释放。下面的代码演示了这个想法:
$a = new stdClass;
debug_zval_dump($a);
$b = $a;
debug_zval_dump($a);
$c = $a;
debug_zval_dump($a);
$c = null; // destroy $c
debug_zval_dump($a);
$b = null; // destroy $b
debug_zval_dump($a);
输出
object(stdClass)#1 (0) refcount(2){
}
object(stdClass)#1 (0) refcount(3){
}
object(stdClass)#1 (0) refcount(4){
}
object(stdClass)#1 (0) refcount(3){
}
object(stdClass)#1 (0) refcount(2){
}
但是当一个变量被修改时,PHP 5 和 7 版本会创建一个变量的副本以保持原始值(变量)不变。
$m1 = memory_get_usage();
$a = str_repeat('a', 1 << 24);
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 16,781,408
$b = $a;
$c = $a;
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 16,781,472
$b[0] = 'x';
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 33,562,880
$c[0] = 'x';
echo number_format(memory_get_usage() - $m1), PHP_EOL;
// 50,344,288
这同样适用于函数参数的上下文。因此,如果一个变量应该用于只读,则不需要显式地通过引用传递它。 Smarty 文档中的文字意味着在大多数情况下,您将变量传递给模板,并且通常不希望模板更改它们。仅当您确实希望在模板中修改变量时才需要通过引用传递变量。相同的概念适用于 PHP 5 及更高版本中的任何函数参数。