返回引用

当您想使用函数来查找应将引用绑定到的变量时,返回引用非常有用。不要使用按引用返回来提高性能。引擎会自动优化这一点。只有在您有正当的技术理由时才返回引用。要返回引用,请使用此语法

<?php
class foo {
public
$value = 42;

public function &
getValue() {
return
$this->value;
}
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue 是 $obj->value 的引用,值为 42。
$obj->value = 2;
echo
$myValue; // 打印 $obj->value 的新值,即 2。
?>
在这个例子中,getValue 函数返回的对象的属性将被设置,而不是复制,因为它在不使用引用语法的情况下将是复制。

注意: 与参数传递不同,这里您必须在两个地方都使用 & - 指示您要按引用返回,而不是副本,并指示应对 $myValue 进行引用绑定,而不是通常的赋值。

注意: 如果您尝试从函数返回一个引用,语法为:return ($this->value); 这将不起作用,因为您试图按引用返回表达式的结果,而不是变量。您只能从函数中按引用返回变量 - 别的什么都不能返回。

要使用返回的引用,您必须使用引用赋值

<?php
function &collector() {
static
$collection = array();
return
$collection;
}
$collection = &collector();
$collection[] = 'foo';
?>
要将返回的引用传递给另一个需要引用的函数,您可以使用此语法
<?php
function &collector() {
static
$collection = array();
return
$collection;
}
array_push(collector(), 'foo');
?>

注意: 请注意,array_push(&collector(), 'foo');不起作用,它会导致致命错误。

添加注释

用户贡献的注释 19 个注释

120
Spad-XIII
16 年前
对 minikomp dot com 处的 pixel 例子的一个小补充
<?php

function &func(){
static
$static = 0;
$static++;
return
$static;
}

$var1 =& func();
echo
"var1:", $var1; // 1
func();
func();
echo
"var1:", $var1; // 3
$var2 = func(); // 赋值不带 &
echo "var2:", $var2; // 4
func();
func();
echo
"var1:", $var1; // 6
echo "var2:", $var2; // 仍然为 4

?>
20
szymoncofalik at gmail dot com
13 年前
有时,您希望使用返回引用的函数返回 NULL,以指示元素链的结束。但是,这会生成 E_NOTICE。这里有一个小技巧,可以防止这种情况

<?php
class Foo {
const
$nullGuard = NULL;
// ... 一些声明和定义
public function &next() {
// ...
if (!$end) return $bar;
else return
$this->nullGuard;
}
}
?>

通过这样做,您可以像这样进行操作,而不会出现通知

<?php
$f
= new Foo();
// ...
while (($item = $f->next()) != NULL) {
// ...
}
?>

您也可以使用全局变量
global $nullGuard;
return $nullGuard;
21
stanlemon at mac dot com
16 年前
我还没有看到任何人注意到 PHP5 中的链式方法调用。当在 PHP5 中通过方法返回一个对象时,默认情况下它是按引用返回的,并且新的 Zend Engine 2 允许您从那些返回的对象中链式调用方法。例如,考虑以下代码

<?php

class Foo {

protected
$bar;

public function
__construct() {
$this->bar = new Bar();

print
"Foo\n";
}

public function
getBar() {
return
$this->bar;
}
}

class
Bar {

public function
__construct() {
print
"Bar\n";
}

public function
helloWorld() {
print
"Hello World\n";
}
}

function
test() {
return new
Foo();
}

test()->getBar()->helloWorld();

?>

请注意,我们如何调用 test(),它不在对象上,而是返回了一个 Foo 实例,然后是 Foo 上的一个方法,getBar(),它返回了一个 Bar 实例,最后调用了它的一个方法 helloWorld()。熟悉其他解释型语言(例如 Java)的人会认识到这种功能。出于某种原因,这种更改似乎没有得到很好的记录,因此希望有人会发现它有用。
14
obscvresovl at NOSPAM dot hotmail dot com
19 年前
返回引用的一个例子

<?

$var = 1;
$num = NULL;

function &blah()
{
$var =& $GLOBALS["var"]; # 与 global $var; 相同
$var++;
return $var;
}

$num = &blah();

echo $num; # 2

blah();

echo $num; # 3

?>

注意:如果您从函数中删除 &,则第二个 echo 将为 2,因为没有 &,变量 $num 包含它的返回值,而不是它的返回引用。
9
sandaimespaceman at gmail dot com
15 年前
&b() 函数返回全局作用域中 $a 的引用。

<?php
$a
= 0;
function &
b()
{
global
$a;
return
$a;
}
$c = &b();
$c++;
echo
"
\$a:
$a
\$b:
$c
"
?>

它输出

$a: 1 $b: 1
1
fabian dot picone at gmail dot com
6 年前
此说明似乎不适用于 PHP 7

"注意:如果您尝试使用以下语法从函数返回引用:return ($this->value); 这将不起作用,因为您试图按引用返回表达式的结果,而不是变量。您只能按引用从函数返回变量 - 而不是其他任何东西。从 PHP 5.1.0 开始,如果代码尝试返回动态表达式或 new 运算符的结果,则会发出 E_NOTICE 错误。"

以下代码在没有错误输出的情况下工作。与我在 $this-value 周围没有花括号时相同的结果。

<?php

class foo {
public
$value = 42;

public function &
getValue() {
return (
$this->value);
}
}

$obj = new foo;
$myValue = &$obj->getValue();
$obj->value = 2;
echo
$myValue;
3
rwruck
18 年前
关于在返回引用时使用括号的说明,只有在您试图返回的变量不包含引用时才成立。

<?php
// 将返回引用
function& getref1()
{
$ref =& $GLOBALS['somevar'];
return (
$ref);
}

// 将返回一个值(并发出通知)
function& getref2()
{
$ref = 42;
return (
$ref);
}

// 将返回引用
function& getref3()
{
static
$ref = 42;
return (
$ref);
}
?>
3
civilization28 at gmail dot com
9 年前
Zayfod 在上面给出的例子很有用,但我认为它需要更多解释。应该指出的是,按引用传入的参数可以更改为引用其他内容,导致以后对局部变量的更改不会影响传入的变量

<?php

function & func_b ()
{
$some_var = 2;
return
$some_var;
}

function
func_a (& $param)
{
# $param 这里为 1
$param = & func_b(); # 这里引用被更改,
# "func_a (& $param)" 中的 "&"
# 对此完全没有影响。
# $param 这里为 2
$param++; # 对 $var 没有影响。
}

$var = 1;
func_a($var);
# $var 这里仍然为 1!因为引用已被更改。

?>
2
benjamin dot delespierre at gmail dot com
13 年前
请记住,按引用返回不适用于 __callStatic

<?php
class Test {
private static
$_inst;
public static function &
__callStatic ($name, $args) {
if (!isset(static::
$_inst)){
echo
"create";
static::
$_inst = (object)"test";
}
return static::
$_inst;
}

var_dump($a = &Test::abc()); // 打印 'create'
$a = null;
var_dump(Test::abc()); // 不打印,实例仍然存在于 Test::$_inst 中
?>
1
hawcue at yahoo dot com
20 年前
在使用三元运算符条件?value1:value2 时要小心

查看以下代码

$a=1;
function &foo()
{
global $a;
return isset($a)?$a:null;
}
$b=&foo();
echo $b; // 显示 1
$b=2;
echo $a; // 显示 1(而不是 2!因为 $b 获取了 $a 的副本)

要让 $b 成为 $a 的引用,请在函数中使用 "if..then.."。
0
anisgazig at gmail dot com
2 年前
<?php

$a
= 9;
function &
myF(){
global
$a;
return
$a;
}

// 修改值之前
$func =& myF();
echo
"$a and $func";
echo
"\n";

// 修改值之后
$func++;
echo
"$a and $func";
0
php at thunder-2000 dot com
17 年前
如果您想获取数组的一部分进行操作,可以使用此函数

function &getArrayField(&$array,$path) {
if (!empty($path)) {
if (empty($array[$path[0]])) return NULL;
else return getArrayField($array[$path[0]], array_slice($path, 1));
} else {
return $array;
}
}

像这样使用它

$partArray =& getArrayField($GLOBALS,array("config","modul1"));

您可以操作 $partArray,对 $GLOBALS 也会进行更改。
0
zayfod at yahoo dot com
20 年前
文档此页面的说明存在一个小例外。当您将按引用返回的函数的结果赋值给按引用传入的值时,您不必使用 & 来指示应进行引用绑定。

考虑以下两个例子

<?php

function & func_b ()
{
$some_var = 2;
return
$some_var;
}

function
func_a (& $param)
{
# $param 这里为 1
$param = & func_b();
# $param 这里为 2
}

$var = 1;
func_a($var);
# $var 这里仍然为 1!

?>

第二个例子按预期工作

<?php

function & func_b ()
{
$some_var = 2;
return
$some_var;
}

function
func_a (& $param)
{
# $param 这里为 1
$param = func_b();
# $param 这里为 2
}

$var = 1;
func_a($var);
# $var 这里为 2,按预期

?>

(熟悉 PHP 4.3.0)
-1
spidgorny at gmail dot com
14 年前
当返回对在函数内部实例化的对象成员的引用时,对象会在返回时被销毁(这是一个问题)。更容易看懂代码

<?php

class MemcacheArray {
public
$data;

...

/**
* 超级智能的一行缓存读取和写入!
* 用法 $data = &MemcacheArray::getData(__METHOD__);
* 希望 PHP 会知道 $this->data 仍然被使用
* 并在数据更改后调用析构函数。
* 哎呀,情况并非如此。
*
* @return unknown
*/
function &getData($file, $expire = 3600) {
$o = new MemcacheArray($file, $expire);
return
$o->data;
}
?>

这里,析构函数在 return() 时被调用,引用变成了普通变量。

我的解决方案是在最终退出() 之前将对象存储在池中,但我不喜欢它。还有其他想法吗?

<?php
protected static $instances = array();

function &
getData($file, $expire = 3600) {
$o = new MemcacheArray($file, $expire);
self::$instances[$file] = $o; // 防止对象过早析构
return $o->data;
}
?>
-1
匿名
10 年前
我从使用传递引用的类方法中吸取了惨痛的教训。

简而言之,如果你在类中有一个在声明时用取地址符 (&) 初始化的方法,不要在使用该方法时再使用取地址符,例如 &$this->method();

例如
<?php
class A {
public function &
hello(){
static
$a='';
return
$a;
}
public function
bello(){
$b=&$this->hello(); // 不正确。不要使用取地址符。
$b=$this->hello(); // $b 是对静态变量的引用。
}
?>
-1
jpenna
4 年前
你可以设置引用返回的变量的值,无论是 `static` 函数变量还是对象的 `private` 属性(这非常危险 o.o)。

静态函数变量

<?php
function &func(){
static
$static = 0;
return
$static;
}

$var1 =& func();
echo
"var1:", $var1, "\n"; // 0
func();

$var1 = 90;
echo
"var1:", $var1, "\n"; // 90
echo "static:", func(), "\n"; // 90
?>

私有属性

<?php
class foo {
private
$value = 1;

public function &
getValue() {
return
$this->value;
}

public function
setValue($val) {
$this->value = $val;
}
}

$obj = new foo;
$myValue = &$obj->getValue(); // $myValue 是对 $obj->value 的引用,值为 1。
echo $obj->getValue(); // 1
echo $myValue; // 1
$obj->setValue(5);
echo
$obj->getValue(); // 5
echo $myValue; // 5
$myValue = 1000;
echo
$obj->getValue(); // 1000
echo $myValue; // 1000
?>
-1
contact at infopol dot fr
20 年前
关于返回嵌入在非引用数组中的引用的说明

<?
$foo;

function bar () {
global $foo;
$return = array();
$return[] =& $foo;
return $return;
}

$foo = 1;
$foobar = bar();
$foobar[0] = 2;
echo $foo;
?>

结果为“2”,因为引用被复制了(非常巧妙)。
-2
willem at designhulp dot nl
18 年前
PHP 5 和 PHP 4 在引用方面存在重要区别。

假设你有一个类,其中有一个名为“get_instance”的方法,用于获取对现有类的引用及其属性。

<?php
class mysql {
function
get_instance(){
// 检查对象是否存在
if(empty($_ENV['instances']['mysql'])){
// 尚未存在对象,创建一个对象
$_ENV['instances']['mysql'] = new mysql;
}
// 返回对对象的引用
$ref = &$_ENV['instances']['mysql'];
return
$ref;
}
}
?>

现在要获取现有的对象,可以使用
mysql::get_instance();

虽然这在 PHP 4 和 PHP 5 中都有效,但在 PHP 4 中,所有数据都将丢失,就像它是新对象一样,而在 PHP 5 中,对象中的所有属性都将保留。
-9
pixel at minikomp dot com
16 年前
<?php

function &func(){
static
$static = 0;
$static++;
return
$static;
}

$var =& func();
echo
$var; // 1
func();
func();
func();
func();
echo
$var; // 5

?>
To Top