函数名前面的 & 符号代表什么意思?

23

在函数名前面加上 & 的含义是什么?

这是否意味着 $result 是按引用返回而不是按值返回的? 如果是的话,那正确吗?我记得你不能返回一个对局部变量的引用,因为一旦函数退出它就消失了。

function &query($sql) {
 // ...
 $result = mysql_query($sql);
 return $result;
}

这样的语法在实践中用在哪里呢?

4个回答

9

这是否意味着$result是通过引用而不是值返回的?

是的。

那么这种语法在实践中在哪里使用?

这在PHP 4脚本中更为普遍,因为默认情况下对象是按值传递的。


3
你有没有证据支持你的说法,即在PHP5中对象是按值传递的? - Dennis Haarbrink
1
@nikic:我不认为这证明了对象是按值传递的。如果您将本地变量设置为新值,则它不是同一对象。您必须编写一个修改某些可变类型对象的函数,并显示传入的值没有在外部更改,以证明参数是按值(复制)传递的。 - Dan Tao
1
@nikic:你的例子有点复杂,因为你混合了对象和字符串数据类型。一个正确的例子应该是:$a = new stdClass; $a->prop='foo'; function test($b){ $b->prop = 'bar'; } test($a); echo $a->prop; 正如你所看到的,对象是通过引用传递的 :) - Dennis Haarbrink
@Dennis:是的,通常对象可以被视为引用。但我认为了解它们不是什么以及知道PHP也使用写时复制是值得的。(这是Golemon在博客文章中谈到的第二件事情。) - NikiC
1
PHP中所谓的“对象”始终是按值传递,除非另有说明。PHP4和PHP5之间的区别在于,在PHP5中,您传递对象的引用。 - Artefacto
显示剩余7条评论

7
为了回答你问题的第二部分,这里有一个我必须使用它的地方:魔术方法!
class FooBar {
    private $properties = array();

    public function &__get($name) {
        return $this->properties[$name];
    }

     public function __set($name, $value) {
        $this->properties[$name] = $value;
    }
}

如果我没有使用&,这是不可能的:
$foobar = new FooBar;
$foobar->subArray = array();
$foobar->subArray['FooBar'] = 'Hallo World!';

PHP会抛出一个错误,例如“无法间接修改重载属性”,而不是执行操作。

好吧,这可能只是一个绕过PHP中某些设计缺陷的技巧,但它仍然很有用。

但是,老实说,我现在想不到另一个例子。但我敢打赌还有一些罕见的用例......


7

这是否意味着$result是通过引用而不是值返回的?

不是的。区别在于它可以通过引用返回。例如:

<?php
function &a(&$c) {
    return $c;
}
$c = 1;
$d = a($c);
$d++;
echo $c; //echoes 1, not 2!

为了按引用返回,您需要执行以下操作:
<?php
function &a(&$c) {
    return $c;
}
$c = 1;
$d = &a($c);
$d++;
echo $c; //echoes 2

还有这种语法在实践中用在哪里?

在实践中,当你想让调用方操作被调用方拥有的数据而不告诉他时,你使用它。这很少被使用,因为它违反了封装原则——你可以将返回的引用设置为任何你想要的值;被调用方无法验证它。

nikic给出了一个很好的例子,说明了这种语法何时会在实践中使用。


如果函数的名称前没有&符号定义,你仍然可以返回引用而不是值吗? - Koray Tugay

3
  <?php
    // You may have wondered how a PHP function defined as below behaves:
    function &config_byref()
    {
        static $var = "hello";
        return $var;
    }
    // the value we get is "hello"
    $byref_initial = config_byref();
    // let's change the value
    $byref_initial = "world";
    // Let's get the value again and see
    echo "Byref, new value: " . config_byref() . "\n"; // We still get "hello"
    // However, let’s make a small change:
    // We’ve added an ampersand to the function call as well. In this case, the function returns "world", which is the new value.
    // the value we get is "hello"
    $byref_initial = &config_byref();
    // let's change the value
    $byref_initial = "world";
    // Let's get the value again and see
    echo "Byref, new value: " . config_byref() . "\n"; // We now get "world"
    // If you define the function without the ampersand, like follows:
    // function config_byref()
    // {
    //     static $var = "hello";
    //     return $var;
    // }
    // Then both the test cases that we had previously would return "hello", regardless of whether you put ampersand in the function call or not.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接