温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

PHP中引用的概念是什么

发布时间:2021-07-13 15:44:31 阅读:144 作者:chen 栏目:大数据
PHP开发者专用服务器限时活动,0元免费领,库存有限,领完即止! 点击查看>>

这篇文章主要介绍“PHP中引用的概念是什么”,在日常操作中,相信很多人在PHP中引用的概念是什么问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”PHP中引用的概念是什么”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!

 

彻底搞明白PHP的中引用的概念

之前我们其实已经有过几篇文章讲过引用方面的问题,这次我们来全面的梳理一下引用在PHP到底是怎么回事,它和C中的指针有什么不同,在使用的时候要注意些什么。

 

什么是引用?

在 PHP 中引用意味着用不同的名字访问同一个变量内容。它不是C的指针,保存的并不是内存地址,无法进行指针运算。引用只是符号表的别名。就像 Unix 系统中的硬链接, Windows 系统中的快捷方式。

上面是官方手册中的原文,怎么说呢,引用其实和我们印象中的C里面的指针并不是相同的概念。指针是针对真实内存的操作,引用是针对指向这个内存的符号表的操作。还是从操作系统的快捷方式来说,快捷方式是可以删的,这就是PHP的引用。而C不仅删了快捷方式,还把原文件也给删了,这就是C的指针操作。

// 引用不是指针$a = 1;$b = &$a;echo $a'==='$b, PHP_EOL;unset($b);echo $a'==='$b, PHP_EOL;
 

上面的代码是在PHP中,我们把$b变量指向$a,作为$a的引用变量。然后删除$b,对$a没有任何影响。

#include <stdio.h>#include <stdlib.h>int main(){    // C 中的指针和引用    int a = 1;    int* b = &a;    printf("%i\n", a); // 1    free(b); // free b    printf("%i\n", a); //get error: *** error for object 0x7fff6350da08: pointer being freed was not allocated    return 0;}
 

而C中的引用指针就不行了,我们把b变量删掉后,再打印a变量就直接报错了。

虽然说PHP的底层也是C写得,但我们都知道C中的指针是出了名的变态,没有一定的功底非常容易出错。所以PHP的开发者没有暴露C的原始指针能力,而是采用了和Java之类的类似的引用能力。这也是现代语言的特性,不需要我们过多的关注过于底层的能力,而将更多的时间放在业务实现上。

 

引用在数组和对象中的使用

如果具有引用的数组被拷贝,其值不会解除引用。对于数组传值给函数也是如此。

$arr1 = ["a""b"];$t1 = &$arr1[1];$arr2 = $arr1;$arr2[1] = "c";var_dump($arr1);// array(2) {//     [0]=>//     string(1"a"//     [1]=>//     &string(1"c"// }$arr1 = ["a""b"];$t1 = &$arr1[1];unset($t1); // unset 掉引用$arr2 = $arr1;$arr2[1] = "c";var_dump($arr1);// array(2) {//     [0]=>//     string(1"a"//     [1]=>//     string(1"b"// }
 

这个其实挺有意思的,我们对比这两个例子可以看出一个问题,$t变量指向$arr[1]的引用。$arr2直接=这个$arr1,没有使用引用,然后$arr2修改了$arr2[1]的内容,$arr1相应的内容也发生了改变,如果unset掉$t变量,则$arr1相应的内容就不会发生改变。对此,我在文档中找到了下面的解释:

由于PHP内部工作的特殊性,如果对数组的单个元素进行引用,然后复制数组,无论是通过赋值还是通过函数调用中的值传递,都会将引用复制为数组的一部分。这意味着对任一数组中任何此类元素的更改都将在另一个数组(和其他引用中)中重复,即使数组具有不同的作用域(例如,一个是函数内部的参数,另一个是全局的)!在复制时没有引用的元素,以及在复制数组后分配给其他元素的引用,将正常工作(即独立于其他数组)。

不仅仅是数组,对象的引用也会有一些好玩的问题。

$o1 = new stdClass();$o1->a = 'a';var_dump($o1);// object(stdClass)#1 (1) {//   ["a"]=>//   string(1) "a"// }$o2 = &$o1;$o3 = $o1;$o2->a = 'aa';var_dump($o1);// object(stdClass)#1 (1) {//   ["a"]=>//   string(2) "aa"// }var_dump($o3); // $o2修改了$a为'aa',$o3也变成了'aa'// object(stdClass)#1 (1) {//   ["a"]=>//   string(2) "aa"// }$o1->a = 'aaa';$o1 = null;var_dump($o2); // $o2引用变成了null// NULLvar_dump($o3); // $o3不仅引用还存在,并且$a变成了'aaa'// object(stdClass)#1 (1) {//   ["a"]=>//   string(3) "aaa"// }
 

上面例子中有三个对象,$o1、$o2、$o3,其中,$o2是对$o1的引用,$o3是直接赋值为$o1。对$o2属性的操作不仅会反映在$o1中,也会反映到$o3中。其实我们之前专门有一篇文章就讲的这个问题,首先对象默认赋值就是引用,其次这个例子很好地证明了引用就是一个符号表的绑定。删除了快捷方式对原始对象和其他快捷方式没有任何影响。大家可以参考:对象赋值在PHP中到底是不是引用?

 

引用的传递

关于引用在方法参数上的传递,最重要的是记住两点:一是方法内部修改了变量外部也会变,这是引用的特性嘛;二是只能传递变量、New 语句、从函数中返回的引用三种类型。

error_reporting(E_ALL);function foo(&$var){    $var++;    echo 'foo:'$var;}function bar() // Note the missing &{    $a = 5;    return $a;}foo(bar()); // 自 PHP 5.0.5 起导致致命错误,自 PHP 5.1.1 起导致严格模式错误            // 自 PHP 7.0 起导致 notice 信息,Notice: Only variables should be passed by referencefoo($a = 5); // 表达式,不是变量, Notice: Only variables should be passed by reference// foo(5); // 导致致命错误 !5是个常量!///////////////////////////////// 正确的传递类型$a = 5;foo($a); // 变量function &baz(){    $a = 5;    return $a;}foo(baz()); // 从函数中返回的引用function foo1(&$var){    print_r($var);}foo1(new stdClass()); // new 表达式
   

引用的返回

引用的返回并不是经常使用的一个能力。文档中的原文是:不要用返回引用来增加性能,引擎足够聪明来自己进行优化。仅在有合理的技术原因时才返回引用!

$a 1;function &test(){    global $a;    return $a;}$b = &test($a);$b 2;echo $a, PHP_EOL;
 

当你想要返回一个引用变量的时候,一定要给方法定义和方法调用的时候都使用&符号。这个是需要注意的点。当其他地方修改原本的变量值或者返回的变量值经过修改后,都会影响到所有调用这个值的地方。所以说,引用的返回是比较危险的,因为你不清楚什么时候在什么地方这个值可能发生了修改,对于bug的排查会非常困难。

 

引用的取消

取消引用其实就是直接unset掉变量就可以了。但是一定要记住,PHP中的引用是指向的符号表,对原始真实的值是不起作用的,所以即使unset掉了最原始的那个变量,对其它引用赋值的变量也不会有影响!!

$a = 1;$b = &$a;$c = &$b;$b = 2;echo '定义引用后:'$a'==='$b'==='$c, PHP_EOL;unset($b);$b = 3;echo '取消$b的引用,不影响$a、$c:'$a'==='$b'==='$c, PHP_EOL;$b = &$a;unset($a);echo '取消$a,不影响$b、$c:'$a'==='$b'==='$c, PHP_EOL;// 定义引用后:2===2===2// 取消$b的引用:2===3===2// 取消$a,不影响$c:===3===2$a = 1;$b = & $a;$c = & $b; // $a$b$c reference the same content '1'$a = NULL; // All variables $a$b or $c are unsetecho '所有引用成空:'$a'==='$b'==='$c, PHP_EOL;
   

总结

这一次算是比较彻底的把引用说了个透。关于PHP的引用只要记住了它的定义就非常好理解了,最直观的就是当成是操作系统的快捷方式就好了,并没有我们想象中的那么难,和C的指针相比真的只是娃娃级别,多多练习多多复习自然就能很好地掌握使用啦!

测试代码:https://github.com/zhangyue0503/dev-blog/blob/master/php/202002/source/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%98%8E%E7%99%BDPHP%E7%9A%84%E4%B8%AD%E5%BC%95%E7%94%A8%E7%9A%84%E6%A6%82%E5%BF%B5.php

参考文档:https://www.php.net/manual/zh/language.references.whatare.phphttps://www.php.net/manual/zh/language.references.whatdo.phphttps://www.php.net/manual/zh/language.references.arent.phphttps://www.php.net/manual/zh/language.references.pass.phphttps://www.php.net/manual/zh/language.references.return.phphttps://www.php.net/manual/zh/language.references.unset.phphttps://www.php.net/manual/zh/language.references.spot.php

到此,关于“PHP中引用的概念是什么”的学习就结束了,希望能够解决大家的疑惑。理论与实践的搭配能更好的帮助大家学习,快去试试吧!若想继续学习更多相关知识,请继续关注亿速云网站,小编会继续努力为大家带来更多实用的文章!

亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

原文链接:https://my.oschina.net/u/4580631/blog/4362246

php
AI

开发者交流群×