首頁  >  文章  >  後端開發  >  PHP之引用

PHP之引用

巴扎黑
巴扎黑原創
2016-11-23 13:15:111015瀏覽

所謂PHP的引用,就是不同的名字存取同一個變數內容。可用在變數、函數以及物件上,用法就是在它們前面加上&符號。以下來細說下引用的類型與功能:

 

一、引用類型 

1.1、變數引用: 兩個變數指向同一個內容

Php  

<?php  
  $a = "abc";   
  $b = &$a;   
  echo $a;//这里输出:abc   
  echo $b;//这里输出:abc   
    
  $b = "done";   
  echo $a;//这里$a的值变为done, 所以输出done   
  echo $b;//这里输出done  
?>

程式碼  

function test(&$a)  
{  
    $a=$a+100;   
}  
  
$b=1;  
  
test($b); //这里$b传递给函数的其实是$b的变量内容所处的内存地址,通过在函数里改变$a的值,就可以改变$b的值了   
  
echo $b;//输出101

 

要注意的是,在這裡test(1); 的話就會出錯,原因自己去想 

1.3、函數引用

Php代碼 $ ()方式呼叫函數,只是將函數的值賦給$a而已, 而$a做任何改變都不會影響到函數中的$b, 而透過$a=&test()方式調用函數呢, 他的作用是將return $b中的$b變數的記憶體位址與$a變數的記憶體位址指向了同一個地方, 即產生了相當於這樣的效果($a=&b;) 所以改變$a的值, 也同時改變了$b的值, 所以在執行了

$a=&test(); 

$a=5;

以後,$b的值變為了5 


這裡是為了方便理解函數的引用返回才使用靜態變量,其實函數的引用回傳多用在物件中

 

1.4、物件的引用

Php程式碼  

function &test()   
{  
    static $b=0;//申明一个静态变量  
    $b=$b+1;  
    echo $b;  
    return $b;  
}  
  
$a=test();//$b的值:1  
  
$a=5;  
$a=test();//$b的值:2  
  
$a=&test();//$b的值:3  
  
$a=5;  
$a=test();//$b的值:6

 

以上程式碼是在PH

class testa  
{  
    var $abc="ABC";   
}  
  
$b=new testa;  
$c = &$b; // or $c = $b;  
echo $b->abc;//这里输出ABC   
echo $c->abc;//这里输出ABC   
$b->abc="DEF";   
echo $c->abc;//这里输出DEF

 

以上程式碼是在PHP5中的效果量;是透過引用來實現的。上例中$b=new a; $c=$b; 其實等效於$b=new a; $c=&$b; 

PHP5中預設就是透過引用來呼叫對象, 但有時你可能會想建立一個物件的副本,並希望原來的物件的改變不影響副本。 為了這樣的目的,PHP定義了一個特殊的方法,稱為__clone. 

二、引用的作用


如果程序比較大,引用同一個對象的變量比較多,並且希望用完該對象後手工清除它,個人建議用"&" 方式,然後用$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 永遠是呼叫它的物件的引用。

 


PS:

PHP有個好處就是可利用其擁有的自動垃圾回收機制(釋放記憶體)。即不需要在使用完變數後做任何釋放記憶體的處理,PHP會幫你完成。當然,我們可以按自己的意願呼叫 unset() 函數來釋放內存,但通常不需要這麼做。

不過在PHP裡,至少有一種情況內存不會得到自動釋放,如下面:

如果兩個對象之間存在著相互引用的關係,如“父對象-子對象”,對父物件呼叫unset()不會釋放在子物件中引用父物件的記憶體(即便父物件被垃圾回收,也不行)。


這個時候,即便是手動呼叫 unset()。詳情可考:http://bugs.php.net/bug.php?id=33595 。

折的方法是在unset() 函數中呼叫物件中的__destruct() 方法;


 

 

------------------ -------------------------------------------------- ----------------


補充:

php中對於位址的指向(類似指標)功能不是由使用者自己來實現的,是由Zend核心實現的,php中引用採用的是「寫時拷貝」的原理,就是除非發生寫入操作,指向同一個位址的變數或物件是不會被拷貝的。

通俗的講 

1:如果有下面的代碼 

$a="ABC"; 
$b=$a; 

其實此時,$a與$b都是指向同一內存地址,而並不是指$a與$b佔用不同的記憶體 

2:如果在上面的程式碼基礎上加上如下程式碼 

$a="EFG"; 

由於$a與$b所指向的記憶體的資料要重新寫一次了,此時Zend核心會自動判斷,自動為$b生產一個$a的資料拷貝,重新申請一塊記憶體進行儲存。



陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn