提问人:oucil 提问时间:3/28/2014 最后编辑:Communityoucil 更新时间:2/20/2022 访问量:1013
PHP 方法关于引用参数或显式返回值的最佳实践
Best practice for PHP methods with regard to reference parameter or explicit return value
问:
我已经使用过这两种方法很多次,但我最近想知道为什么我没有对其中一种进行标准化,或者是否有最佳实践以及其背后的原因是什么。
虽然 PHP 的返回引用页面非常清楚地说明了关于返回引用:
仅当您有正当的技术理由时才返回引用。
...在讨论参数和返回方法时,传递引用页面并不那么清晰。
请看以下两个示例:
参考返回
class foo {
public static function bar(&$val) {
$val++;
}
}
$input = 0;
foo::bar($input);
echo $input; // outputs 1
显式返回
class foo {
public static function bar($val) {
$val++;
return $val;
}
}
$input = 0;
$input = foo::bar($input);
echo $input; // outputs 1
这两种方法执行相同的任务并返回相同的值,但它们完成它的方式略有不同。我知道这种情况(同一任务的多个解决方案)在PHP中很常见,但我的问题是......
上述两种方法中的一种是否优于另一种方法,如果是,为什么?
我应该指出,我确实看到了其他类似的问题:按引用传递与按值传递有什么区别? 但它们处理的是效果和例子,而不是为什么一个比另一个更受欢迎。
编辑:为了省去其他人阅读关于问题优点的冗长讨论的麻烦......
在考虑底层代码(无论是 PHP 还是 C 代码)中固有的开销或优化时,我希望有一些具体的东西,以及这种效果在转换为 OpCode 并放入潜在的数千个应用程序服务器的上下文后将如何转化为性能。小的优化可能会对月底的底线产生很大的影响。
我没想到会有这种不情愿,但我的猜测是,乍一看,当你考虑基本的编程要求时,并没有区别。我们的情况不同,所以我应该在前面更具体。
如果还有人愿意参与进来,我全都听进去。
答:
如前所述,这取决于你。
在我看来,显式返回始终是最好的方式,所以如果你在 6 个月内回到你的代码,你不会问自己这个 var 是如何递增的!$input
当代码有 10 行时,确实很容易找出它的作用,但当你在处理一个更复杂的应用程序时就不行了。
事实上,你需要在显式返回中编写更多的代码,但它的可读性要强得多,你之后的开发者将很容易理解你做了什么,这对于你的应用程序的可维护性非常重要。
评论
关于PHP中的引用,以下是一些需要注意的问题:
PHP 使用写入时复制来处理赋值,因此不会将$b写入不同的变量容器,直到发生使两个变量不同的更改。可能发生的一种更改类型是,对$b的引用是由另一个变量进行的,例如(为了使它成为引用,它现在必须复制$b)。在 C++ 中,引用没有自己的内存地址,并且被视为对象本身的别名(即使在某些情况下您仍然可以有悬空引用)。在 PHP 中,引用“......不像 C 指针 [指针 - 不是 C++ 引用];例如,你不能使用它们执行指针运算,它们不是实际的内存地址,等等。鉴于上述信息,我们看到在进行更改之前,复制变量不会占用额外的内存。在某些情况下,PHP 中的引用会添加到内存中。这种情况发生在 和 (不同 ) 时,因为即使 $b 从 $a 没有更改,它也需要在单独的 zval 变量容器中$b自己的引用跟踪机制,因此触发对$b的写入。
$b = $a
$c = &$b
$b = $a
$c = &$b
$c = &$a
PHP的当前版本和旧版本之间的差异可能导致不同的处理方式:“在PHP 4中,对象被视为其他变量,因此当将它们用作函数参数或进行赋值时,它们会被复制。在 PHP 5 中,它们总是通过引用传递的。
语言,无论是人类还是计算机,通常都倾向于尽可能地简化(除非复杂性的好处大于简单性):
- 跟踪来自函数/方法的引用更改更加困难(因为如果不查看函数/方法,就无法查看哪些参数作为引用传递)。
- 跟踪涉及基础引用的更改更加困难。
- 核心功能有时会以不同的方式处理引用。
- 例如:不取消设置$a,但用于取消$b与$a的关联(在本例中,$b未设置,$a保留其值)。
$b = &a; unset($b);
- 例如:array_filter() 不适用于传递的引用。
- 这不起作用:
$a=array(0,'', -1); $b = &a; print_r(array_filter($b));
- 这不起作用:
- 例如:不取消设置$a,但用于取消$b与$a的关联(在本例中,$b未设置,$a保留其值)。
意外结果:
- 如下代码无法按预期工作:
$array1 = array(1,2);
$x = &$array1[1]; // Unused reference
$array2 = $array1; // reference now also applies to $array2 !
$array2[1]=22; // (changing [0] will not affect $array1)
print_r($array1);
Produces:
Array (
[0] => 1
[1] => 22 // var_dump() will show the & here
)
下一个:无法修改函数内的数组
评论