1

已经非常彻底地解释了,如果它们是技术原因,您只能在 PHP 中通过引用传递,因为 Copy-On-Write 基本上使性能等效。据我了解,如果它从未更改过,它永远不会复制对象。

但是,如果函数确实更改了变量,但您的代码不再使用它/不使用任何已更改的部分怎么办?是否更改原始代码对代码无关紧要。是的,PHP 优化器可能会考虑这种情况,但我没有理由相信它会这样做。

传递单个引用肯定会比复制一个巨大的数组或对象快得多。

那么这是通过引用传递的好情况吗?

例如,假设您传入一个 DomCrawler (只不过是一个大的 [html 格式化] 字符串,除了在这种特定情况下它是通过引用隐式传递的)。爬行一点并提取一些信息。在许多情况下,您不需要将 Crawler 重置为其原始位置,因为您根本不会再次使用它。另外,想象一下我们确实使用了 DOMCrawler,我们从中读取 URI。该函数没有改变这一点,所以通过引用或值传递仍然是等价的,但是通过引用传递不会明显更优化吗?我认为这种情况对于任何优化者来说都很难发现。

4

3 回答 3

3

那么这是通过引用传递的好情况吗?

不。

好的。想象一下,你有一个 $bigString 并将它传递给一个函数,该函数修改它并用它做一些事情,而调用者再也不需要它了。通过引用传递最初更快,因为它避免了复制。但是,这仍然是一个坏主意。

(1) 如果另一个调用者调用您的函数希望继续使用该变量,那么事情就会中断。该引用基本上违反了封装。

(2) 只要​​您在函数外部有多个非引用变量引用该值,只需创建引用就需要再次复制。(变量值保存在可能是非引用(修改时复制)或引用(修改时不做任何特殊操作)的容器中,因此对于引用变量和非引用变量,请尝试在同时,它必须被复制。)

(3) 由于上述原因,像在函数中调用 strlen 这样无辜的事情将不得不复制值,因为 strlen 的参数是按值传递的,这是规范。现在假设您在循环中调用了一些函数,例如 substr 和 strlen,并且您每次都在制作数据的新副本。

(4) DDR3 RAM 每秒可以推超过 10 GB,而 CPU 缓存 RAM 天知道有多快。我认为 PHP 性能比字符串或数组复制需要多长时间更需要担心。

不要将参考用于迷信的性能提升。它永远不会起作用。

如果您真的想避免复制,那么正确的方法可能是将您的函数作为照顾变量的对象的方法:

class Thing {
    private $bigString;

    public function foo() {
        $this->bigString[0] = 'x';
    }
}

然后您避免复制,获得封装的好处并且没有引用的微妙之处。

PS:DomCrawler 不是一个很好的例子,因为它是一个对象。PHP 对象无论如何都不是写时复制(我认为它们是,但是有一个额外的间接级别,所以写时复制的唯一部分是一个小指针容器,或类似的东西)。

于 2013-03-11T17:56:32.693 回答
1

出于与避免 goto 相同的原因,我一直避免通过引用传递。

$a = myFunction($a);

比阅读和重用更容易myFunction(&$a);

于 2013-08-27T12:54:03.053 回答
0

根据我对 PHP 系统的理解,一切都是通过“引用”传递的。因此,如果您要传递巨大的数组或对象,它们总是通过“引用”传递。

我把“参考”放在引号中,因为这里有两种不同的类型:

  • 显式引用是您向 php 指定您希望将其作为引用跟踪的位置
  • 隐式引用是您希望将其作为值跟踪的位置,而不是

PHP 默认为隐式引用。

因此,在您更改隐式引用之前,不会对性能产生影响。在这种情况下,PHP 会将值分配到单独的内存地址并更新您的引用。

如果编译器检测到该变量不再被使用或不再在作用域内,GC 会将其铲除。

于 2013-03-11T06:42:57.187 回答