在 PHP 中通过引用返回

Posted

技术标签:

【中文标题】在 PHP 中通过引用返回【英文标题】:Return by reference in PHP 【发布时间】:2011-11-19 07:35:06 【问题描述】:

我尝试了谷歌搜索,尝试了 php 文档,搜索了 Stack Overflow 的答案,但找不到任何令人满意的东西。我正在读一本书,其中作者使用了Return by Reference,但从未解释过它是什么。作者使用的代码是

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

有人可以用简单的话解释一下这个概念吗?

【问题讨论】:

PHP docs 是对此的最终答案——请务必浏览所有“参考说明”部分。 Cmon Jon,我已经说过我已经阅读了文档,并且承认我从那里并没有很好地理解它。这就是我在这里问的原因,如果您有任何版本要解释,我将不胜感激:) Jon 提供的链接通过示例很好地解释了这一点。 @IbrahimAzharArmar:通过示例代码和解释添加了完整答案,希望对您有所帮助:) 【参考方案1】:

假设你有这个类:

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"; 

See it in action.

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

【讨论】:

另一方面,所有这些都在文档中有效,但是当接收端没有提到&符号时会发生什么,以及如何在类中禁用按值复制?例如。对于单例类。因为如果您必须指望调用者表现良好,那么知道您想要返回一个值没有多大意义,是吗?【参考方案2】:

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

就是这样。


更容易将其视为“PHP 允许您引用返回值”,而不是 PHP 通过引用返回。如上所述,您只需放置一个 & 来告诉 PHP 您想要这个,如果您不放置它并尝试对 $var =& somefunction() 执行此操作,您将收到错误“仅应通过引用分配变量”。

为了消除对 Jon 的回答的一些困惑。实际上没有必要有两个单独的函数,一个按引用返回,一个按值返回;在某些项目约定之外。 &允许它通过引用返回,它不强制它通过引用返回。

例如。用于引用和非引用分配的相同函数

\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

参考很好,但是如果您不熟悉它们,请遵循以下规则:

仅在处理大型数组或类似的非对象数据结构时才考虑使用引用 永远不要引用对象(如果可以避免的话) 仅当值保留在对象的静态属性或属性中时才允许函数通过引用传递(即,它不是函数内部的临时变量)

异常显然是非常实用的用途(即,当您真正想要共享一个值以简化操作它的代码时)。

再次,永远不要引用对象(这毫无意义!)

【讨论】:

【参考方案3】:

您发布的示例可能来自 PHP4 或更早版本。不再需要通过引用返回对象,因为在 PHP5+ 中它们几乎总是以这种方式自动完成。

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

见return references in PHP docs

【讨论】:

我已经说过我已经阅读过文档,这对我没有任何解释。我想了解更多。 在某些情况下,通过引用返回可能很好,但我是一个强有力的对手。另见我的博客:schlueters.de/blog/archives/125-Do-not-use-PHP-references.html

以上是关于在 PHP 中通过引用返回的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 PHP 中通过引用传递?

如何在php中通过引用传递无限参数[重复]

如何在 C++ 中通过引用返回向量

如何在 C++ 中通过引用返回类对象?

何时在 PHP 中通过引用传递

在 PHP 中通过 ODBC(使用 PDO)查询雪花返回不正确的数据