摘要:即產生了相當于這樣的效果,所以改變的值也同時改變了的值。不要用返回引用來增加性能,引擎足夠聰明來自己進行優化。只能從函數返回引用變量沒別的方法。
關鍵是對global的誤解,之前以為在函數中global變量,就是把函數外部的變量拿進函數內部使用,但似乎我錯了
引用傳遞+unset+global理解
php的引用(就是在變量、函數、對象等前面加上&符號)
在PHP中引用的意思是:不同的名字訪問同一個內存地址
1、變量的引用:PHP的引用允許你用兩個變量來指向同一個內存空間
代碼:
結果:
2、函數的傳址調用
這里$num傳遞給函數的其實是$num所處的內存地址,通過在函數里改變$a的值,就可以改變$num的值了
3、函數的引用返回 —— 沒太明白什么時候用
和參數傳遞不同,函數的引用返回必須在兩個地方都用 & 符號(函數聲明時、函數調用時) —— 指出返回的是一個引用,而不是通常的一個拷貝
結果:
結果:
結果:
結果:
下面解釋下:
盡管函數聲明方式是 function &test() 這樣,但通過$a = test() 這種方式的函數調用得到的其實不是函數的引用返回,這跟普通的函數調用沒有區別
PHP規定通過 $a = &test() 并且在聲明函數時也使用了&,得到的才是函數的引用返回
用上面的例子來解釋就是,$a = test() 這種方式調用函數,只是將函數的返回值賦給 $a 而已,而$a做任何改變都不會影響到函數中的$b
而通過 $a = &test() 方式調用函數呢(前提是聲明函數時也用了&),它的作用是將 return $b 中的 $b 變量的內存地址與 $a 變量的內存地址指向了同一個地方。即產生了相當于這樣的效果 ($a=&$b), 所以改變 $a 的值也同時改變了 $b 的值。所以在執行了
$a = &test();
$a = 5;
以后,$b的值也變為了5
再來個例子加深理解:
PHP里的函數的引用在定義及調用都要在函數名前加上 &
結果:
這里是為了讓大家理解函數的引用返回才使用靜態變量的,其實函數的引用返回多用在對象中
很多時候我們會看到這樣的代碼(出自 CI 框架源碼):
$class =& load_class("a","b");
手冊里是這么寫的:引用返回用在當想用函數找到引用應該被綁定在哪一個變量上面時。不要用返回引用來增加性能,引擎足夠聰明來自己進行優化。僅在有合理的技術原因時才返回引用!要返回引用,使用此語法:
和參數傳遞不同,這里必須在兩個地方都用 & 符號——指出返回的是一個引用,而不是通常的一個拷貝,同樣也指出 $myValue 是作為引用的綁定,而不是通常的賦值
如果試圖這樣從函數返回引用:return ($this->value);,這將不會起作用,因為在試圖返回一個表達式的結果而不是一個引用的變量。只能從函數返回引用變量——沒別的方法。如果代碼試圖返回一個動態表達式或 new 運算符的結果,自 PHP 4.4.0 和 PHP 5.1.0 起會發出一條 E_NOTICE 錯誤
似懂非懂?那么我們來改寫一下程序吧,讓它變成一個常規的函數:
結果:
現在能理解“引用返回用在當想用函數找到引用應該被綁定在哪一個變量上面時”這句話了吧,函數 &getValue() 把引用綁定在成員變量 $value 上了。正常來說,$obj = new foo; 產生的 $obj 是一個copy,它的成員變量 $value 與函數 getValue() 不存在“別名”(引用)關系(額,不太懂)
4、對象的引用
結果:
以上代碼是在PHP5中的運行效果,在PHP5中對象的復制是通過引用來實現的。上列中$b=new a; $c=$b; 其實等效于$b=new a; $c=&$b; PHP5中默認就是通過引用來調用對象, 但有時你可能想建立一個對象的副本,并希望原來的對象的改變不影響到副本,為了這樣的目的,PHP定義了一個特殊的方法,稱為__clone
php5中對于大數組的傳遞,建議用 "&" 方式,畢竟節省內存空間使用
5、取消引用
重要的是刪除引用的變量,當你 unset 一個引用,只是斷開了變量名和內存地址之間的綁定。只是unset的變量訪問不了,這并不意味著內存地址被銷毀了
不會 unset $b,只是 $a
地址(引用)傳遞,只是多個變量指向了同一地址(內存空間)
unset一個,并不能unset掉地址空間
根據這個原理,我們來屢屢$a和$GLOBALS["a"]之間的關系
代碼1:
代碼2:
結果:
代碼3:
結果:
根據這三段代碼的結果,$a和$GLOBALS["a"]在內存中的關系肯定不是這樣的
如果是這樣的話,unset掉一個,另一個應該還是存在的
所以個人猜測關系應該是這樣的:
其中一個是另一個的別名
關于這個問題,也問了一些人,各有個的說法,況且都牽扯到了PHP底層機制,暫且放一放,按照上面說的來理解吧
6、global
這里的$num =& $GLOBALS["num"]; $num是函數里的$num,函數里的$num指向了$GLOBALS["num"]的內存地址
global 引用
當在函數中用 global $var 聲明一個變量時實際上建立了一個到全局變量的引用。也就是說和這樣做是相同的:
$var =& $GLOBALS["var"];
這意味著,unset $var 不會 unset 全局變量
$this 在一個對象的方法中,永遠是調用它的對象的引用
再來一個例子:
結果:
為什么會是0 5呢?
global在函數中產生一個指向函數外部變量的別名變量,而不是真的把函數外的變量拿到函數中使用
一旦改變了別名變量(函數內部的變量)的指向地址
$var2 =& $var1;
其實就是函數中$var2的引用指向了$var1的內存地址
只是函數中$var2的指向發生了變化,函數內部變量的變化只在函數的局部產生效應,在函數外部$var2的指向物理內存地址并沒有變化,還是它自己,所以根本就沒有改變函數外$var2的值
$GLOBALS[]確確實實調用的是函數外部的變量,函數內外始終保持一致!
結果:
7、寫時拷貝
php中對于地址的指向(類似指針)功能不是由用戶自己來實現的,是由Zend核心實現的,php中引用采用的是寫時拷貝的原理,就是除非發生寫操作,指向同一個地址的變量或者對象是不會被拷貝的
通俗的講:
① 如果有下面的代碼
$a="ABC"; $b=$a;
其實此時,$a與$b都是指向同一內存地址,而并不是$a與$b占用不同的內存
② 如果在上面的代碼基礎上再加上如下代碼
$a="EFG";
由于$a與$b所指向的內存的數據要重新寫一次了,此時Zend核心會自動判斷,自動為$b產生一個$a的數據拷貝,重新申請一塊內存進行存儲
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/21305.html
摘要:引用可以被看作是文件系統中的硬鏈接。如果具有引用的數組被復制,其值不會解除引用。如果試圖這樣從函數返回引用,將會報錯,因為函數在試圖返回一個表達式的結果而不是一個引用的變量。這并不意味著變量內容被銷毀了。 1. 什么是引用 在 PHP 中引用是指用不同的名字訪問同一個變量內容。PHP 中的變量名和變量內容是不一樣的, 因此同樣的內容可以有不同的名字。最接近的比喻是 Unix 的文件名和...
摘要:中的對象傳遞然后說一下之后的默認情況下的對象是通過引用傳遞的這件事情。如此時,其實表示的并不是是的引用,和可以說是沒什么關系的,有關系的是實例化類得到的對象。 首先引發這篇博文的是來源于這篇帖子:https://segmentfault.com/q/10... 經過了思考之后,我決定把回答思考變成博客做一下記錄,如有不對之處,歡迎指正。 指針與引用 首先,引用和指針是不一樣的,指針在...
摘要:銷毀給定的變量函數的行為依賴于給定的變量的類型而有所不同。以上例程會輸出如果在函數中一個靜態變量,那么在函數內部此靜態變量之前將被銷毀。但是,當再次調用此函數時,此靜態變量將被復原為上次被銷毀之前的值。 isset() isset()-檢測變量是否設置 語法: bool isset (mixed $var [,mixed $var [,$....]]) 說明: 如果var存在則返回tr...
摘要:是一個關聯數組,每一個變量為一個元素,鍵名對應變量名,值對應變量的內容。之所以在全局范圍內存在,是因為是一個超全局變量。 概念 單一個global是一個關鍵字,通常附加在變量前,用于將變量聲明至全局作用域;$GLOBALS是預定義的超全局變量,把變量扔到里邊的話一樣可以帶到全局去。 $GLOBALS 是一個關聯數組,每一個變量為一個元素,鍵名對應變量名,值對應變量的內容。$GLOBAL...
摘要:發布時最大的變動是對象處理方式。這很容易被誤解為引用,但是存儲器的引用與引用是完全不同的概念。使用引用是一件不好的事情,除了引用本身不好,并且還會使性能下降這個事實外,使用引用這種方式會使得代碼難以維護。 showImg(https://segmentfault.com/img/remote/1460000014082570); 去年我參加了很多次會議,其中八次會議里我進行了相關發言,...
閱讀 3720·2023-04-25 17:45
閱讀 3431·2021-09-04 16:40
閱讀 1002·2019-08-30 13:54
閱讀 2131·2019-08-29 12:59
閱讀 1400·2019-08-26 12:11
閱讀 3280·2019-08-23 15:17
閱讀 1522·2019-08-23 12:07
閱讀 3881·2019-08-22 18:00