为什么在PHP中很少使用引用?


26

我有一些C ++知识,并且知道那里经常使用指针,但是我已经开始研究PHP开放源代码,而且我从没看过在方法中使用引用的代码。

相反,代码始终使用返回值,而不是将对变量的引用传递给方法,该方法然后更改该变量的值并只返回它。

我已经读到使用引用会占用更少的内存,那么为什么不在PHP中使用它们呢?


19
使用按引用传递参数是“副作用编程”-在读取代码时,使用函数返回单个值的方法明显更清晰。也就是说,相当多的PHP核心功能都使用了引用。
Halfer

3
PHP默认通过引用传递对象。

2
数组排序是通过引用传递的核心PHP函数的主要体现
Mark Ba​​ker

2
PHP引用不是指针,并且如果您不完全希望它们出现的话,通常会很麻烦。
lanzz

2
如果您需要多次退货,return array($foo, $bar);以及list($A, $B) = foobar();
Izkata

Answers:


49

您关于引用很少使用的断言是错误的。正如其他人已经提到的那样,有很多使用引用的本机函数,值得注意的例子包括数组排序函数preg_match()/ preg_match_all()。如果您在代码中使用这些功能中的任何一个,那么您还将使用引用。

继续,PHP中的引用不是指针。由于您来自C ++背景,因此我可以理解其中的困惑,但是PHP引用是完全不同的野兽,它们是symbol table的别名。您可能希望从C ++引用获得的任何性能提升都根本不适用于PHP引用。

实际上,在大多数情况下,按值传递比按引用传递更快且内存占用更少。Zend Engine是PHP的核心,它使用写时复制优化机制,该机制只有在变量被修改后才创建副本。通过引用传递通常会破坏写时复制模式,并且无论您是否修改该值,都需要一个副本。

不要害怕在需要时在PHP中使用引用,但不要只是为了进行微优化而这样做。请记住,过早的优化是万恶之源

进一步阅读:


感谢您的纠正@NikiC。这个答案有点懒惰……
扬尼斯

为了完成答案,很高兴指出所有对象都是通过PHP的引用传递的。
Florian Margaine

@FlorianMargaine并不完全准确(请参阅进一步阅读中的第二个链接)。
扬尼斯

2
@FlorianMargaine不,两者是非常不同的,重要的是要意识到为什么会这样。
phant0m

3
@FlorianMargaine不,假设对象通过PHP的引用传递的:f($obj)给定的对象function f($x) { $x = new X; }$obj引用与调用之前不同的对象f()。但是,由于对象不是通过引用传递的,因此,如果要使用PHP执行此操作,则不会修改$ obj。这样,PHP的作用与Java相同。
phant0m 2013年

8

PHP已经进行了写时复制操作,在您更改内容之前不会创建新值,因此使用引用不会节省太多内存。这样做甚至会弄乱PHP在内部做的一些事情,以减少内存使用,使情况变得更糟。

此外,引用通常会使事情变得有些不可思议。默认值(也是大多数人期望的)是按值传递。当我$i使用某个功能时,必须注意该功能是否$i完全神秘地更改为其他功能,从而使事情变得非常复杂,从而制作防御性副本以防万一。($i如果该值是一个对象,它已经可以修改,但我认为不应。)

基本上,我只找到传递按引用的“走出去”的参数是有用的,这意味着变量我希望能找回从功能,而不是传中,一拉preg_match&$matches。即使对于明显修改要传入的对象的函数(如sort或)array_pop,也感觉有些刺眼...但这就是我们所坚持的。


5

PHP是一种面向Web的语言。
网页投放速度很快,应该是轻量级的。
通常的PHP程序的寿命只有几分之一秒,并且消耗几百千字节的内存。
这种优化没有用。


1
这个。不需要指针/引用,因为它不会像C ++这样的低级混乱。
肯尼思·沃登

8
为什么这篇文章获得5+?它确实a)没有回答问题b)不正确

1
那么引用很慢并且会占用太多内存吗?
火箭Hazmat

1
@RocketHazmat是的,很奇怪,这是事实。
yannis 2013年

3

飞行中的一些原因:

  • PHP是一种脚本语言,并非旨在用作核心嵌入式软件(基本上,在脚本末尾会清除内存),
  • 从PHP5开始,对象参数隐式传递引用(因此PHP在“后面”使用传递引用)。

1
关于第二点,请参见:php.net/manual/en/language.oop5.references.php
yannis

2

我认为这只是开发人员的选择,与语言无关。许多PHP代码(内置和非内置)都使用引用。看一下PHP中的数组函数,其中许多使用引用。 preg_match使用引用。

我认为开发人员选择不使用引用的原因之一是因为它可能会造成混淆。您调用一个函数,并且其中一个变量可能(也可能不会)被更新,因为它是一个引用。因此,在调试时,可能尚不清楚为什么$xjsut 的值会发生神奇的变化。


1

您的问题的根本问题是您假设这在C ++中也是常见的。不是。我们不喜欢输出参数,并尽可能少地使用它们-它们仅在C样式API中才真正常见。


0

我知道许多这样做的php函数。看看preg_match()例如。$matches将通过引用传递

如果要自己编写一个函数,该函数通过引用来接受参数,请使用以下语法

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ a和$ b通过引用传递$ c通过值传递。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.