很多时候我们会看到这样的代码(出自 CI 框架源码):

1 $class =& load_class('a','b');

我们都知道其中的'&'是指引用,但是它的作用是什么呢?它能够解决什么样的问题呢?带着这些问题,我们开始了解下“引用返回”。

引用返回

手册里是这么写的:引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!要返回引用,使用此语法:

01 <?php
02 class foo {
03     public $value = 42;
04  
05     public function &getValue() {
06         return $this->value;
07     }
08 }
09  
10 $obj new foo;
11 // $myValue is a reference to $obj->value, which is 42.
12 // $myValue 是 $obj->value 的引用,它们的值都是 42
13 $myValue = &$obj->getValue();
14 // 对 $obj->value 重新复制,会影响到 $myValue 的值
15 $obj->value = 2;
16 // prints the new value of $obj->value, i.e. 2.
17 echo $myValue;  // 程序输出 2
18 ?>

本例中 getValue() 函数所返回的对象的属性将被赋值,而不是拷贝,就和没有用引用语法一样。

参数传递不同,这里必须在两个地方都用 & 符号——指出返回的是一个引用,而不是通常的一个拷贝,同样也指出 $myValue 是作为引用的绑定,而不是通常的赋值。

如果试图这样从函数返回引用:return ($this->value);,这将不会起作用,因为在试图返回一个表达式的结果而不是一个引用的变量。只能从函数返回引用变量——没别的方法。如果代码试图返回一个动态表达式或 new 运算符的结果,自 PHP 4.4.0 和 PHP 5.1.0 起会发出一条 E_NOTICE 错误。

似懂非懂?那么我们来改写一下程序吧,让它变成一个常规的函数:

01 <?php
02 class foo {
03     public $value = 42;
04  
05     public function getValue() {
06         return $this->value;
07     }
08 }
09  
10 $obj new foo;
11 $myValue $obj->getValue();
12 $obj->value = 2;
13  
14 echo $obj->value;  // 程序输出 2
15 echo $myValue;  // 程序输出 42
16 ?>

现在能理解“引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时”这句话了吧,函数 &getValue() 把引用绑定在成员变量 $value 上了。正常来说,$obj = new foo; 产生的 $obj 是一个copy,它的成员变量 $value 与函数 getValue() 不存在“别名”(引用)关系。

一些简单的例子

看下面的简单例子,尝试去理解引用返回。

01 <?php
02  
03 function &test()
04 {
05     // 声明一个静态变量
06     static $b = 0;
07  
08     $b $b+1;
09     echo $b;
10     return $b;
11 }
12  
13 $a = test();    //这条语句会输出 $b 的值为 1
14  
15 $a = 5;
16 $a = test();    //这条语句会输出 $b 的值为2
17  
18 $a = &test();   //这条语句会输出 $b 的值为3
19  
20 $a = 5;
21 $a = test();    //这条语句会输出 $b的值 为6
22  
23 ?>

程序运行结果:

1 1
2 2
3 3
4 6
  •  
    尽管函数声明方式是 function &test() 这样,但我们通过这种方式 $a = test() 的函数调用得到的其实不是函数的引用返回,这跟普通的函数调用没有区别。PHP 规定通过 $a = &test() 这种方式得到的才是函数的引用返回。

用上面的例子来解释就是,$a = test() 这种方式调用函数,只是将函数的值赋给 $a 而已,而$a做任何改变都不会影响到函数中的$b。

而通过 $a = &test() 方式调用函数呢,它的作用是将 return $b 中的 $b 变量的内存地址与 $a 变量的内存地址指向了同一个地方。即产生了相当于这样的效果 ($a=&$b), 所以改变 $a 的值也同时改变了 $b 的值。所以在执行了

1 $a = &test();
2 $a = 5;

以后,$b的值变为了5。

再来个程序例子加深理解:

01 <?php
02 /*
03 ** 值传递和引用传递,值传递传递的是值的一个复本,引用传递传递的是值指向的内存地址
04 */
05  
06 // 函数的引用,定义时也要加上 &
07 function &func($a,$b){ 
08     // 这里为了更直观看到效果,定义一个静态变量
09     static $result = 0;    
10     $result+=$a+$b;
11     echo $result.'<br />';
12     return $result;
13 }
14   
15 $a $b = 10;
16  
17 // PHP里这样写函数的引用调用,和调用普通函数没有区别(只是将函数的返回值复制给$c这个变量,$c做任何改变不会影响上面函数中的$result)
18 // 要记住:PHP里的函数引用定义及调用都要在函数名前加上 &
19 $c = func($a,$b);
20 // 第一次执行func(),其静态变量$result的值变为 20(10+10)
21  
22 // 改变$c的值,不会对下面一行语句产生影响
23 $c = 666; 
24 // 第二次执行func(),其静态变量$result的值变为 40(20+10+10)
25 $c = func($a,$b);
26  
27 echo '<hr />';
28  
29 // 这样才是PHP中引用函数的调用方式
30 $d = &func($a,$b); 
31 // 第三次执行func(),其静态变量$result的值变为 40(40+10+10)
32 $d = 888;
33 // 第四次执行func(),其静态变量$result的值变为 908(888+10+10)
34 $d = func($a,$b);
35  
36 ?>

PHP 函数的“引用返回”概念释疑(转)的更多相关文章

  1. PHP引用(&)初探:函数的引用返回

    函数的引用返回 先看代码: <?php function &test() { static $b=0;//申明一个静态变量 $b=$b+1; echo $b; return $b; } ...

  2. php函数名前添加& 函数的引用返回

    function &test(){ static $b=0; $b= $b+1; return $b; } $a= test(); echo $a,"\n"; $a = 3 ...

  3. php函数的引用返回

    <?php function &test(){ static $b = 1; $b += 2; return $b; } $a = &test(); $a =8; $c = te ...

  4. 详解php中函数的引用传递和返回 (附代码)

    本篇文章带大家了解一下php的引用,详细介绍一下函数的引用传递和引用返回.有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助.php的引用(就是在变量或者函数.对象等前面加上&符号 ...

  5. php变量的引用及函数的引用

    Php变量的引用及函数的引用放回 变量的引用    $a="ABC";    $b =&$a;    echo $a;//这里输出:ABC    echo $b;//这里输 ...

  6. php引用(&)详解及注意事项——引用返回function &a();&a()

    http://www.cnblogs.com/xiaochaohuashengmi/archive/2011/09/10/2173092.html 函数的引用返回 先看代码 <?php func ...

  7. 常量函数、常量引用参数、常量引用返回值[C++]

    1. 关于常量引用正像在C语言中使用指针一样,C++中通常使用引用 有一个函数... foo()并且这个函数返回一个引用...... & foo()...., 一个指向位图(Bitmap)的引 ...

  8. [二] java8 函数式接口详解 函数接口详解 lambda表达式 匿名函数 方法引用使用含义 函数式接口实例 如何定义函数式接口

    函数式接口详细定义 package java.lang; import java.lang.annotation.*; /** * An informative annotation type use ...

  9. C++命名空间、函数重载、缺省参数、内联函数、引用

    一 .C++入门 1.C++关键字 2.命名空间 3.C++输入&输出 4.缺省参数 5.函数重载 6.引用 7.内联函数 8.auto关键字 9.基于范围的for循环 10.指针空值null ...

随机推荐

  1. python - zipfile

    参考:http://www.cnblogs.com/sislcb/archive/2008/11/28/1342822.html zipfile - python处理zip文件的压缩与解压 ZipFi ...

  2. jquery中eq和get的区别与使用方法

    $("p").eq(0).css("color") //因为eq(num)返回的是个jq对象,所以可以用jq的方法css使用get来获得第一个p标签的color ...

  3. 极光推送 api ios参数问题

    这是首个app项目,推送用的是极光推送jpush 由于用官方文档出现接收多条的问题,在网上找到一套封装好的,非常感觉这位开发者 //推送.指定人error_reporting(E_ALL^E_NOTI ...

  4. 我摘录的js代码

    1.修改样式 document.getElementByIdx( "div1").style.display = "none"; 2.鼠标悬停图标变小手 sty ...

  5. 手机端的META你有多了解?

    我们先来简单了解下meta标签:meta指元素可提供有关页面的元信息(meta-information),比如针对搜索引擎和更新频度的描述和关键词. 标签位于文档的头部,不包含任何内容. 标签的属性定 ...

  6. CSS让图片垂直居中的几种技巧 三种方法介绍

    在网页设计过程中,有时候会希望图片垂直居中的情况.而且,需要垂直居中的图片的高度也不确定,这就会给页面的布局带来一定的挑战.下面总结了一下,曾经使用过的几种方法来使图片垂直居中,除了第一种方法只限于标 ...

  7. 错误: 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner

    错误: 找不到或无法加载主类 scala.tools.nsc.MainGenericRunner 原因: Sacala安装路径中包含空格.

  8. 【转载】之 破解 (【原创】Xenocode Postbuild 2009 加壳破解 (不断更新中...))

    声明 本文转载,感谢原作者dotNetSafe分享 [原创]Xenocode Postbuild 2009 加壳破解 (不断更新中...) http://bbs.pediy.com/showthrea ...

  9. BZOJ 1015 星球大战

    Description 很久以前,在一个遥远的星系,一个黑暗的帝国靠着它的超级武器统治者整个星系.某一天,凭着一个偶然的机遇,一支反抗军摧毁了帝国的超级武器,并攻下了星系中几乎所有的星球.这些星球通过 ...

  10. OpenSource.com 评出 2014 年十佳开源软件

    Docker 应用容器平台 “电源管理和虚拟化以相同的方式允许我们从服务器利用率中获取最大的利益.如何真正的解决虚拟化,这世界第一难题仍然是普遍存在的.Docker 自从 2013 年开源以来,刚好在 ...