一篇搞懂php的引用

image

引用变量的解释

  1. 引用是什么?
    再PHP中引用意味着用不同的名字访问同一个变量的内容;
    注意: 在PHP中,变量名和变量内容是不一样的,因此同样的内容可以有不同的名字。最接近的比喻是`Unix` 的 `文件名` 和 `文件本身` -- 变量名是目录条目,而变量内容则是文件本身,引用可以被看做是`Unix`文件系统的 `硬链接` ;
    example1.php
<?php
 $var = "foo";
    $ref1 =& $var; // 引用 $var 的内存空间
    //安装debug扩展,可以使用此方法打印
    xdebug_debug_zval('var');//(refcount=2, is_ref=1)string 'foo' (length=3)
   
    echo $ref1; // >Notice:  Undefined variable: ref1
    echo $var; // >foo
?>
  1. 引用不是什么?
    引用不是指针 , 这意味着一下的结构不会产生预期的效果
<?php
function foo(&$var)
{
    $var = &$GLOBALS["baz"];
}
foo($bar);
?>

这将使 foo 函数中的 $var 变量在函数调用时和 $bar 绑定在一起,但接着又被重新绑定到了 $GLOBALS["baz"] 上面。不可能通过引用机制将 $bar 在函数调用范围内绑定到别的变量上面,因为在函数 foo 中并没有变量 $bar(它被表示为 $var,但是 $var 只有变量内容而没有调用符号表中的名字到值的绑定)。
example2.php

<?php
$ref = [1,2,3];
$c = count($ref);
$foo = ['A'];
 
for($i=0;$i<$c;$i++)
    $foo[] =& $ref[$i];

print_r($foo);
print_r($ref);

$ref = [4,5,6];

print_r($foo);
print_r($ref);
?>
/* 打印结果:
Array
(
    [0] => A
    [1] => 1
    [2] => 2
    [3] => 3
)
Array
(
    [0] => 1
    [1] => 2
    [2] => 3
)
Array
(
    [0] => A
    [1] => 1
    [2] => 2
    [3] => 3
)
Array
(
    [0] => 4
    [1] => 5
    [2] => 6
)
*/

注意example2.php$ref 经历了 Copy-on-Write 缩写为 COW 写时复制

  1. 引用做什么?
    PHP的引用允许用两个变量来指向同一个内容
    example3.php
<?php
$a =& $b;
?>

这意味着 $a$b 指向了同一个变量。
注意:
a> $a$b 在这里是完全相同的,这并不是 $a 指向了 $b 或者相反,而是 $a$b 指向了同一个地方。
b> 如果具有引用的数组被拷贝,其值不会解除引用。对于数组传值给函数也是如此。
c> 如果对一个未定义的变量进行引用赋值、引用参数传递或引用返回,则会自动创建该变量。

example4.php

<?php
// 对未定义的变量使用引用
function foo(&$var) { }
foo($a); // 创建 $a,并用 null 赋值 

$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)

$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>

d>同样的语法可以用在函数中,它返回引用,以及用在 new 运算符中:

example4.php

?>
$bar = &new fooclass();
$fll = &find_var($bar);
?>

自 PHP 5 起,自动返回引用,因此在此使用 =& 已经过时了并且会产生 E_STRICT 级别的消息。
e> 不用 & 运算符导致对象生成了一个拷贝。如果在类中用 $this,它将作用于该类当前的实例。
没有用 & 的赋值将拷贝这个实例(例如对象)并且 $this 将作用于这个拷贝上,这并不总是想要的结果。
由于性能和内存消耗的问题,通常只想工作在一个实例上面。
尽管可以用 @ 运算符来抑制构造函数中的任何错误信息,例如用 @new,但用 &new 语句时这不起效果。这是 Zend 引擎的一个限制并且会导致一个解析错误。
f> 注意:如果在一个函数内部给一个声明为 global 的变量赋于一个引用,该引用只在函数内部可见。可以通过使用 $GLOBALS 数组避免这一点。

example5.php

<?php
$var1 = "Example variable";
$var2 = "";

function global_references($use_globals)
{
    global $var1, $var2;
    if (!$use_globals) {
        $var2 =& $var1; // visible only inside the function
    } else {
        $GLOBALS["var2"] =& $var1; // visible also in global context
    }
}

global_references(false);
echo "var2 is set to '$var2'\n"; // var2 is set to ''
global_references(true);
echo "var2 is set to '$var2'\n"; // var2 is set to 'Example variable'
?>

global $var; 当成是 $var =& $GLOBALS['var']; 的简写。从而将其它引用赋给 $var 只改变了本地变量的引用。

example6.php

<?php
$ref = 0;
$row =& $ref;
foreach (array(1, 2, 3) as $row) {
    // do something
}
echo $ref; // 3  数组中的最后一个元素
?>
  1. 引用的其他用途:
    引用做的第二件事是用引用传递变量。这是通过在函数内建立一个本地变量并且该变量在呼叫范围内引用了同一个内容来实现的
    example7.php
<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
?>

将使 $a 变成 6。这是因为在 foo 函数中变量 $var 指向了和 $a 指向的同一个内容。更多详细解释见引用传递

  1. 引用传递
    可以将一个变量通过引用传递给函数,这样该函数就可以修改其参数的值;
    example8.php
<?php
function foo(&$var)
{
    $var++;
}

$a=5;
foo($a);
// $a is 6 here
?>

注意:
在函数调用时没有引用符号——只有 函数定义 中有。光是函数定义就足够使参数通过引用来正确传递了。在最近版本的 PHP 中如果把 & 用在 foo(&$a); 中会得到一条警告说"Call-time pass-by-reference"已经过时了。
以下内容可以通过引用传递:
1> 变量,例如 foo($a)
2> New 语句,例如 foo(new foobar())
3> 从函数中返回的引用;

example9.php

//以下内容可以通过引用传递:
<?php
function &bar()
{
    $a = 5;
    return $a;
}
foo(bar());
?>
  1. 引用返回
    引用返回用在当想用函数找到引用应该被绑定在哪一个变量上面时。不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!

example10.php

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

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

$obj = new foo;
$myValue = &$obj->getValue(); //42
$obj->value = 2;
echo $myValue;                // 打印 $obj->value,  2.
?>

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

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

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

  1. 取消引用
    当 unset 一个引用,只是断开了变量名和变量内容之间的绑定。这并不意味着变量内容被销毁了。
<?php
$a = 1;
$b =& $a;
unset($a);
?>

不会 unset $b,只是 $a
再拿这个和 Unixunlink 调用来类比一下可能有助于理解。
7.引用定位
许多 PHP 的语法结构是通过引用机制实现的,所以上述有关引用绑定的一切也都适用于这些结构。一些结构,例如引用传递和返回,已经在上面提到了。
其他的引用结构有:
1> global :当用 global $var 声明一个变量时实际上建立了一个到全局变量的引用。

<?php
$var =& $GLOBALS["var"];
?>

这意味着,例如,unset $var 不会 unset 全局变量。
2> $this :在一个对象的方法中,$this 永远是调用它的对象的引用。

以上就是引用的全部内容;

相关题目:

<?php
/**
 * 每次循环的结果是什么?最终程序执行完的结果是什么?为什么?
 */
$data = ['a', 'b', 'c'];
foreach ($data as $key => $val){
    $val = &$data[$key];
    var_dump($data);
}

var_dump($data);
?>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • 第2章 基本语法 2.1 概述 基本句法和变量 语句 JavaScript程序的执行单位为行(line),也就是一...
    悟名先生阅读 4,055评论 0 13
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,099评论 18 139
  • 这是孙伟每天一篇文章的第20天 下午读书会的一位朋友到店里交谈社群这一块问题,他谈到了她想做70后的社群的构...
    孙伟爱学习阅读 264评论 0 0
  • 杨辉三角,又叫帕斯卡三角形,是一个三角形矩阵,其顶端是 1,视为(row0).第1列(row1)(1&1)两个1,...
    有苦向瓜诉说阅读 2,118评论 0 2
  • 雷长虹老师很勤奋,倒是我,没有和老师一起就懒散了。笔也收了,颜料也干了,新买的颜料也没拆封。总是抱怨时间不够,其实...
    梦海蓉阅读 2,126评论 11 24