在PHP中通过引用返回


Return by reference in PHP

我试着谷歌,尝试PHP文档,搜索堆栈溢出的答案,但无法找到任何令人满意的。我正在读一本书,其中作者使用了Return by Reference,但从未解释它是什么。作者使用的代码是

function &getSchool() {
    return $this->school;
}

谁能举一个简单的例子来解释一下这个概念?

假设你有这样一个类:

class Fruit {
    private $color = "red";
    public function getColor() {
        return $this->color;
    }
    public function &getColorByRef() {
        return $this->color;
    }
} 

类有一个私有属性和两个方法可以访问它。一个按值返回(默认行为),另一个按引用返回。两者的区别在于:

  • 当使用第一种方法时,你可以对返回值进行更改,这些更改不会在Fruit的私有属性中反映出来,因为你实际上是在修改属性值的副本。
  • 当使用第二种方法时,您实际上获得了Fruit::$color 的别名——一个不同的名称,您通过它引用相同的变量。因此,如果你对它做任何事情(包括修改它的内容),你实际上是直接对属性的值执行相同的操作。

下面是一些测试代码:

echo "'nTEST RUN 1:'n'n";
$fruit = new Fruit;
$color = $fruit->getColor();
echo "Fruit's color is $color'n"; 
$color = "green"; // does nothing, but bear with me
$color = $fruit->getColor();
echo "Fruit's color is $color'n"; 
echo "'nTEST RUN 2:'n'n";
$fruit = new Fruit;
$color = &$fruit->getColorByRef(); // also need to put & here
echo "Fruit's color is $color'n"; 
$color = "green"; // now this changes the actual property of $fruit
$color = $fruit->getColor();
echo "Fruit's color is $color'n"; 

实际操作

警告:我觉得有必要提到引用,虽然它们确实有合法的用途,但它们是应该很少使用的特性之一,并且只有在您首先仔细考虑了任何替代的情况下才能使用。缺乏经验的程序员倾向于过度使用引用,因为他们看到引用可以帮助他们解决特定的问题,而不会同时看到使用引用的缺点(作为一种高级特性,其细微差别远不明显)。

简单规则:如果您将&放在PHP函数名称前面,您可以在调用函数时使用&(即:它的返回值)就好像它是一个变量而不是一个函数。


更容易理解为"PHP允许您引用返回值",而不是PHP通过引用返回。如上所述,您只需放置&来告诉PHP您想要这个,如果您不放置$var =& somefunction()并尝试这样做,您将得到错误"只有变量应该通过引用分配"。

为了澄清乔恩回答中的一些困惑。实际上没有必要有两个独立的函数,一个通过引用返回,一个通过值返回;在一些项目约定之外。&只有允许通过引用返回,它不强制通过引用返回。

。用于引用和非引用赋值的相同函数

'header('content-type: text/plain');
class Demo
{
    protected $example = 'original value';
    function & example()
    {
        return $this->example;
    }
}
$demo = new Demo;
#1 - pass by value
$var1 = $demo->example();
$var1 = 'var1 value';
echo '$demo->example() => '.$demo->example().PHP_EOL;
echo PHP_EOL;
#2 - pass by reference
$var2 =& $demo->example();
$var2 = 'var2 value';
echo '$demo->example() => '.$demo->example().PHP_EOL;
echo '$var1 => '.$var1.PHP_EOL;
echo '$var2 => '.$var2.PHP_EOL;
echo PHP_EOL;
#3 - altering other references
$var3 =& $demo->example();
$var3 = 'var3 value';
echo '$demo->example() => '.$demo->example().PHP_EOL;
echo '$var1 => '.$var1.PHP_EOL;
echo '$var2 => '.$var2.PHP_EOL;
echo '$var3 => '.$var3.PHP_EOL;
echo PHP_EOL;
exit;

$demo->example() => original value
$demo->example() => var2 value
$var1 => var1 value
$var2 => var2 value
$demo->example() => var3 value
$var1 => var1 value
$var2 => var3 value
$var3 => var3 value
参考文献是很好的,但是如果你不熟悉它们,请遵循以下规则:
  • 只有在处理大型数组或类似的非对象数据结构时才考虑使用引用
  • 永远不要引用对象(如果可以避免的话)
  • 仅允许在对象的静态属性或属性中维护值时通过引用传递函数。它不是函数内的临时变量)

异常显然是非常实用的用法(例如:当你想要共享一个值来简化操作它的代码时)

再次强调,永远不要引用对象(这是没有意义的!)

你发布的例子可能来自PHP4或更早的版本。不再需要通过引用返回对象,因为在PHP5+中几乎总是这样自动完成的。

通过引用返回当你想使用一个函数来找出引用应该绑定到哪个变量。不要使用通过引用返回来提高性能。发动机将自动优化它自己。仅在以下情况下返回引用您有一个有效的技术理由来这样做。

参见PHP文档中的返回引用