PHP傳值和傳引用、傳地址的區別是什么?
傳值:
是把實參的值賦值給形參,那么對形參的修改,不會影響實參的值
傳地址:
是傳值的一種特殊方式,只是他傳遞的是地址,不是普通的如int
那么傳地址以后,實參和形參都指向同一個對象
傳引用:
真正的以地址的方式傳遞參數
傳遞以后,形參和實參都是同一個對象,只是他們名字不同而已
對形參的修改將影響實參的值
從函數調用的角度理解比較好
傳值:
函數參數壓棧的是參數的副本,任何的修改是在副本上作用,沒有作用在原來的變量上。
傳指針:
壓棧的是指針變量的副本。
當你對指針解指針操作時,其值是指向原來的那個變量,所以對原來變量操作。
傳引用:
壓棧的是引用的副本。由於引用是指向某個變量的,對引用的操作其實就是對他指向的變量的操作。(作用和傳指針一樣,只是引用少了解指針的草紙)
函數參數傳遞機制的基本理論
函數參數傳遞機制問題在本質上是調用函數(過程)和被調用函數(過程)在調用發生時進行通信的方法問題;函數的目的終歸是對目標數據的處理(常見的有,設置變量的值等其它屬性)。
基本的參數傳遞機制有兩種:值傳遞和引用傳遞。
以下討論稱調用其他函數的函數為主調函數,被調用的函數為被調函數:
值傳遞(passl-by-value)過程中,被調函數的形式參數作為被調函數的局部變量處理,即在堆棧中開辟了內存空間以存放由主調函數放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。(ps:即值傳遞過程中,函數是對作為局部變量的形參進行的操作!)
引用傳遞(pass-by-reference)過程中,被調函數的形式參數雖然也作為局部變量在堆棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參的任何操作都被處理成間接尋址,即通過堆棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的實參變量。 ps:表面對形參的操作實際是對實參變量的操作。
如上所述,值傳遞和引用傳遞對實參變量的處理過程是不一樣的,函數對值的操作和對引用的操作的機制是不一樣;形參總是被作為局部變量來處理的,函數會根據在其內存空間中存儲的是實參的值的副本還是實參的地址的副本分別處理,至於函數是如何區分值和地址的,我不得而知,貌似也不必知道。
僅討論一下值傳遞和引用:
所謂值傳遞,就是說僅將對象的值傳遞給目標對象,就相當於copy;系統將為目標對象重新開辟一個完全相同的內存空間。
所謂引用,就是說將對象在內存中的地址傳遞給目標對象,就相當於使目標對象和原始對象對應同一個內存存儲空間。此時,如果對目標對象進行修改,內存中的數據也會改變。
引用的作用
如果程序比較大,引用同一個對象的變量比較多,並且希望用完該對象后手工清除它,個人建議用 "&" 方式,然后用$var=null的方式清除. 其它時候還是用php5的默認方式吧. 另外, php5中對於大數組的傳遞,建議用 "&" 方式, 畢竟節省內存空間使用。
取消引用
當你 unset 一個引用,只是斷開了變量名和變量內容之間的綁定。這並不意味着變量內容被銷毀了。例如:
<?php
$a = 1;
$b =& $a;
unset ($a);
?>
不會 unset $b,只是 $a。
global 引用
當用 global $var 聲明一個變量時實際上建立了一個到全局變量的引用。也就是說和這樣做是相同的:
<?php
$var =& $GLOBALS["var"];
?>
這意味着,例如,unset $var 不會 unset 全局變量。
$this
在一個對象的方法中,$this 永遠是調用它的對象的引用。
補充:
php中對於地址的指向(類似指針)功能不是由用戶自己來實現的,是由Zend核心實現的,php中引用采用的是“寫時拷貝”的原理,就是除非發生寫操作,指向同一個地址的變量或者對象是不會被拷貝的。