前言
去年我参加了很多次会议,其中八次会议里我进行了相关发言,这其中我多次谈到了 PHP 的引用问题,因为很多人对它的理解有所偏差。在深入讨论这个问题之前,我们先回顾一下引用的基本概念,明确什么是“引用传递”。
在 PHP 中引用意味着用不同的名字访问同一个变量内容,不论你用哪个名字对变量做出了运算,其他名字访问的内容也将改变。
让我们通过代码来加深对此的理解。 首先我们写几个简单的语句,把一个变量赋值给另一个变量,并且改变另一个变量:
<"htmlcode"><"htmlcode"><"\$a before calling foo(): $a\n"; $b = foo($a); echo "\$a after the call to foo(): $a\n"; $b = 23; echo "\$a after touching the returned variable: $a\n"; "htmlcode">$a before calling foo(): 23 $a after the call to foo(): 42 $a after touching the returned variable: 42这里我们初始化了一个变量,并把它作为一个引用参数传给了一个函数。函数改变了它,它有了新值。该函数返回同一个变量,我们更改了返回的变量和它的原始值。。。 等等!它没变,不是吗!? —— 没错,可引用就是这样。 具体发生了如下事情:该函数返回了一个引用,引用了 $a 的变量容器 zval,并且通过 = 赋值操作符为它创建了一个副本。
为了修复这个问题,我们需要添加一个额外的 & 操作符:
$b = &foo($a);结果和我们所期望的一样:
$a before calling foo(): 23 $a after the call to foo(): 42 $a after touching the returned value: 23总结一下: PHP 的引用就是同一个变量的别名,想要正确的使用它们可能很难。想要详细了解引用计数,这里有份基础资料,请参阅 手册中的引用计数基本知识 。
PHP 5 发布时最大的变动是『对象处理方式』。一般我们理解为:
在 PHP 4 中,对象被当成变量来对待,所以当对象作为函数传参时,他们是被复制的。但在 PHP 5 中,他们永远是『引用传参』。
以上的理解并不完全正确。其主要目的是遵循『面对对象模式』:对象传参给函数或者方法后,这个函数发送一个指令给对象(例如调用了一个方法)以此来改变对象的状态(例如对象的属性)。因此传参进去的对象必须为同一个。 PHP 4 的面对对象用户使用『引用传参』来解决这个问题,不过很难做到完美。PHP 5 引进了独立于变量容器的『对象存储器』。当一个对象赋值给变量时,变量不再存储整个对象(属性表和其他的『类』信息),而是存储这个对象所在 存储器的引用 —— 当我们复制一个对象变量时,我们复制的是这个『存储器的引用』。这很容易被误解为『引用』,但是『存储器的引用』与『引用』是完全不同的概念。下面的示例代码有助于我们更好地区分:
<"foo"]=> // int(42) // } var_dump($c); // int(42) "htmlcode"><"... looooong string with lots of data ....."; foo(string); "htmlcode">do_something($var);你希望 $var 发生改变吗?—— 当然不会。然而,如果 do_something() 传递的参数是引用,它就可能会改变。
这类 API 的另一个问题是:函数不能链式调用,因而你总会遇到必须使用临时变量的场景。链式调用可能会使可读性降低,但是在许多场景下,链式调用使得代码更加简洁。
关于引用的糟糕的设计决定,我个人最喜欢的一个例子是 PHP 自带的 sort() 函数。sort() 使用一个数组作为引用参数,然后通过引用返回一个排好序的数组。 像常规那样通过值返回一个排好序的数组可能还更好些。当然,这么做是由于历史的原因:sort() 比『写时复制』更早出现。『写时复制』产生于 PHP4,而 sort() 则更早,它早在 PHP 还是作为一种在 Web 上做起事来很方便的东西,而不是真正的成为自己的语言的时候就存在了。
总之: 在 PHP 中,引用是不好的。 不要使用引用。 它们只会惹事生非,另外,不要对使用引用来提升引擎抱有希望。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com狼山资源网 Copyright www.pvsay.com暂无“为何说PHP引用是个坑,要慎用”评论...
稳了!魔兽国服回归的3条重磅消息!官宣时间再确认!
昨天有一位朋友在大神群里分享,自己亚服账号被封号之后居然弹出了国服的封号信息对话框。
这里面让他访问的是一个国服的战网网址,com.cn和后面的zh都非常明白地表明这就是国服战网。
而他在复制这个网址并且进行登录之后,确实是网易的网址,也就是我们熟悉的停服之后国服发布的暴雪游戏产品运营到期开放退款的说明。这是一件比较奇怪的事情,因为以前都没有出现这样的情况,现在突然提示跳转到国服战网的网址,是不是说明了简体中文客户端已经开始进行更新了呢?