2013-03-11 53 views
1

已經很徹底地解釋過,只有在PHP中引用時,如果它們是技術原因這樣做,因爲基本上Copy-On-Write使性能相當。從我所瞭解的情況來看,如果它永遠不會改變,它永遠不會複製對象。通過引用傳遞(當變量可以改變,但沒有必要)

但是如果函數確實改變了變量,但是你的代碼再也不會使用它/不使用任何被改變的部分呢?如果原始文件被更改,則代碼無關緊要。是的,PHP優化器可能會考慮到這種情況,但我沒有理由相信它。

傳遞一個單引用肯定會比複製一個巨大的數組或對象快得多。

那麼這是好的情況,通過引用或不?

例如,假設你傳入一個DomCrawler(不過是一個大的[html格式]字符串,除非它在這個特定情況下通過引用隱式傳遞)。抓取一點並提取一些信息。在許多情況下,您不需要爬行程序重置到其原始位置,因爲您只是不再使用它。 另外,想象後者,我們使用DOMCrawler,我們從中讀取URI。函數沒有改變這個,所以通過引用或值傳遞仍然是等價的,但是通過引用傳遞不會顯着更優化?我認爲這種情況對於任何優化器都很難發現。

+0

有啥問題,重用? – kennypu 2013-03-11 06:17:54

+0

而你的問題是?你不是在猜測設計PHP的人,你是?因爲這太冒昧;) – paulsm4 2013-03-11 06:17:56

+1

我永遠不會明白爲什麼SO討厭/不太理解隱含的問題。 更新的問題。 – Jonathon 2013-03-11 06:19:38

回答

3

那麼,這是好的情況通過引用或不?

好。想象一下,你有一個$ bigString,並將它傳遞給一個函數,該函數修改它並對它執行一些操作,調用者再也不需要它了。由於避免了複製,因此按引用傳遞最初速度更快。但是,這仍然是一個壞主意。 (1)如果一個不同的調用者調用你的函數確實想要繼續使用該變量,事情就會中斷。基準違反封裝。(2)只要你有超過1非參考變量在函數外引用該值,僅僅創建參考需要再次複製。 (變量值保存在可能是非引用(copy-on-modify)或引用(對修改沒有特別要求)的容器中,因此對於引用變量和非引用變量來說,請參考同時,它必須被複制。)

(3)由於上述原因,在函數內調用strlen的無辜內容將不得不復制該值,因爲strlen的參數是通過值傳遞的,規範。現在想象你調用一些函數,比如substr,或者循環中的strlen,並且你每次都會創建一個新的數據副本

(4)DDR3內存可以推每秒CPU緩存RAM各地超過10 GB是天知道有多快。我認爲使用PHP性能需要擔心的是比字符串或陣列副本需要多長時間。

不要使用引用來獲得迷信的性能收益。它從來沒有工作。

如果你真的想避免拷貝,這樣做的正確方法可能是把你的功能爲對象,看起來變量後的方法:

class Thing { 
    private $bigString; 

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

然後你避免複製,獲得封裝的好處以及引用的細微之處。

PS:DomCrawler不是一個很好的例子,因爲它是一個對象。無論如何,PHP對象從來都不是copy-on-write(好吧,我認爲它們是,但還有一個額外的間接級別,所以寫入時複製的唯一部分是一個小指針容器,或類似的東西)。

+0

字符串可以實現爲指向底層不可變字符數據的指針。因此,複製字符串只會複製一個指針,而不涉及複製大量「數據」。 – newacct 2013-03-13 05:03:22

+0

@newacct它確實涉及它。 PHP字符串*是可變的,因此引用和按值分配不能共享相同的數據塊。 – Boann 2013-03-13 08:43:08

+0

值類型在語義上等同於不可變引用類型。更改字符串的字符數據的唯一方法是爲其分配新的字符串。告訴我,這與Java中的字符串有什麼不同? – newacct 2013-03-13 19:14:38

0

從我對PHP系統的理解中,一切都通過「參考」傳遞。所以如果你傳遞巨大的數組或對象,它們總是被「引用」傳遞。

我把引號「參考」原因有2種不同類型的瀏覽:

  • 明確提到是您指定到PHP,你希望它跟蹤作爲參考
  • 隱式引用是希望它跟蹤爲一個值

PHP默認爲隱式引用。

因此,在您更改隱式引用之前,不會有性能影響。在這種情況下,PHP將分配複製值來分隔內存地址並更新您的引用。

如果編譯器檢測到該變量不再被使用或不在範圍內,則GC會將其挖出。

1

我一直避免通過引用傳遞,因爲我避免轉到同一個原因。

$a = myFunction($a); 

更容易閱讀和比myFunction(&$a);

+0

'myFunction(&$ a)'是通過引用傳遞的時間,並且已被棄用,並且從來不推薦。在函數聲明中指定了真正的通過引用。 – newacct 2013-08-28 04:49:21

+0

@newacct寫得越短越好。無論如何,這一切都歸功於個人偏好。我從不關心通過引用傳遞,因爲它不太清楚變量的值究竟在哪裏設置。 – user1119648 2013-08-28 11:10:42