国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 網站 > 建站經驗 > 正文

為何說PHP引用是個坑,要慎用

2019-11-02 14:09:58
字體:
來源:轉載
供稿:網友

前言

去年我參加了很多次會議,其中八次會議里我進行了相關發(fā)言,這其中我多次談到了 PHP 的引用問題,因為很多人對它的理解有所偏差。在深入討論這個問題之前,我們先回顧一下引用的基本概念,明確什么是“引用傳遞”。

在 PHP 中引用意味著用不同的名字訪問同一個變量內容,不論你用哪個名字對變量做出了運算,其他名字訪問的內容也將改變。

讓我們通過代碼來加深對此的理解。 首先我們寫幾個簡單的語句,把一個變量賦值給另一個變量,并且改變另一個變量:

<?php$a = 23;$b = $a;$b = 42;var_dump($a); // int(23)var_dump($b); // int(42)

這個腳本顯示 $a 值仍然為 23  ,而 $b 則等于 42 。出現這個情況的原因是我們得到的是一個拷貝(具體發(fā)生了什么稍后講解。。。)現在我們使用引用來做同樣的事情:

<?php$a = 23;$b = &$a;$b = 42;var_dump($a); // int(42)var_dump($b); // int(42)?>

現在 $a 的值也改變成了 42 。 事實上,$a 和 $b 之間沒有任何區(qū)別,它們都使用了同一個變量容器(又名: zval )。 將這兩者分開的唯一方法是使用 unset() 函數銷毀其中任何一個變量。

在 PHP 中,引用不僅能用在普通語句中,還能用于函數參數和返回值:

<?phpfunction &foo(&$param) { $param = 42; return $param;}$a = 23;echo "/$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";?>

你認為上面的結果是什么呢?―― 沒錯,就像下面這樣:

$a before calling foo(): 23$a after the call to foo(): 42$a after touching the returned variable: 42

這里我們初始化了一個變量,并把它作為一個引用參數傳給了一個函數。函數改變了它,它有了新值。該函數返回同一個變量,我們更改了返回的變量和它的原始值。。。 等等!它沒變,不是嗎!? ―― 沒錯,可引用就是這樣。 具體發(fā)生了如下事情:該函數返回了一個引用,引用了 $a 的變量容器 zval,并且通過 = 賦值操作符為它創(chuàng)建了一個副本。

為了修復這個問題,我們需要添加一個額外的 & 操作符:

$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 發(fā)布時最大的變動是『對象處理方式』。一般我們理解為:

在 PHP 4 中,對象被當成變量來對待,所以當對象作為函數傳參時,他們是被復制的。但在 PHP 5 中,他們永遠是『引用傳參』。

以上的理解并不完全正確。其主要目的是遵循『面對對象模式』:對象傳參給函數或者方法后,這個函數發(fā)送一個指令給對象(例如調用了一個方法)以此來改變對象的狀態(tài)(例如對象的屬性)。因此傳參進去的對象必須為同一個。 PHP 4 的面對對象用戶使用『引用傳參』來解決這個問題,不過很難做到完美。PHP 5 引進了獨立于變量容器的『對象存儲器』。當一個對象賦值給變量時,變量不再存儲整個對象(屬性表和其他的『類』信息),而是存儲這個對象所在 存儲器的引用 ―― 當我們復制一個對象變量時,我們復制的是這個『存儲器的引用』。這很容易被誤解為『引用』,但是『存儲器的引用』與『引用』是完全不同的概念。下面的示例代碼有助于我們更好地區(qū)分:

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 江门市| 孟连| 绿春县| 林西县| 广汉市| 平原县| 雷山县| 宣化县| 嫩江县| 环江| 北川| 册亨县| 巢湖市| 澳门| 礼泉县| 高尔夫| 宜春市| 阜城县| 浦江县| 嘉荫县| 库伦旗| 康马县| 石首市| 景洪市| 女性| 裕民县| 海安县| 白河县| 东至县| 莲花县| 澎湖县| 辉南县| 九寨沟县| 阿城市| 泸水县| 全州县| 那坡县| 浦城县| 盈江县| 徐州市| 朝阳市|