php函數值傳值/地址以及引用的用法


1.先來解釋一下名詞。

 

值傳遞(passl-by-value)過程中,被調函數的形式參數作為被調函數的局部變量處理,即在堆棧中開辟了內存空間以存放由主調函數放進來的實參的值,從而成為了實參的一個副本。值傳遞的特點是被調函數對形式參數的任何操作都是作為局部變量進行,不會影響主調函數的實參變量的值。

 

引用傳遞(pass-by-reference)過程中,被調函數的形式參數雖然也作為局部變量在堆棧中開辟了內存空間,但是這時存放的是由主調函數放進來的實參變量的地址。被調函數對形參的任何操作都被處理成間接尋址,即通過堆棧中存放的地址訪問主調函數中的實參變量。正因為如此,被調函數對形參做的任何操作都影響了主調函數中的。

注意:上面紅字部分說明,應用傳遞不是不開辟空間,是開辟空間的,只不過開辟的空間是用來存放實參變量地址的。

 

2.php中引用的用法有以下三種。

①. 變量的引用賦值: $a = &$b

②. 函數調用時的引用參數傳遞

   1) 早期php是在調用時通過&符號傳遞引用類型的變量, 比如: func(&$arg);

   2) 后來, 函數的引用類型參數被規定為需要在函數聲明時定義, 不如: function func(&$arg);

注意:引用聲明時定義引用類型參數后,運行時引用參數傳遞被廢棄,需要在php.ini中增加allow_call_time_pass_reference來開啟.

③. 函數返回引用類型,這種應用方式需要聲明函數時,在函數名前增加&符號,並且,在調用時,要用引用賦值方式, 實例代碼如下:

function &func() { 
    return $a; 
} 
$a = func();  //這種調用方式得到的不是引用傳值 
$a =& func(); //這樣調用才是引用傳值

請看下面詳細的例子:

$a = 1; 
function &func(&$a) { 
  return $a; 
} 
$b = func($a); 
$c =& func($a); 
$b = 2; 
echo "a: $a, b: $b, c: $c. <br />/n"; 
//輸出a: 1, b: 2, c: 1. 
//可見對$b的修改不會影響$a 
$c = 3; 
echo "a: $a, b: $b, c: $c. <br />/n"; 
//輸出a: 3, b: 2, c: 3. 
//可見對$c的修改會影響$a 

  

3.php各種數據類型傳值/指針

一、基本數據類型的傳值

/* **************************************************** */  
function testvar($k){ 
 $k = 40; 
} 
$c = 30; 
//給一個函數參數傳一個基本數據類型(整型,布爾,字符 ...), 實際上傳的就是值 ; 
testvar($c); 
echo $c;//結果是:30 
function testvar2(&$k){ 
 $k = 40; 
} 
$e = 30; 
//給一個函數參數傳一個基本數據類型(整型,布爾,字符 ...), 實際上傳的y就是地址 ; 
testvar2($e); 
echo $e;//結果是:40 
 
/* **************************************************** */ 

二、數組(默認情況下是復制一份數據),如要傳地址則&$arr

 1 $arr1 = array(-1,5,0); 
 2 function testArr($arr){ 
 3  for($i=0;$i<count ($arr);$i++){ 
 4   for($j=$i+1;$j<count($arr);$j++){ 
 5    if($arr[$i]>$arr[$j]){ 
 6     $temp = $arr[$i]; 
 7     $arr[$i] = $arr[$j]; 
 8     $arr[$j] = $temp; 
 9    } 
10   } 
11  
12  } 
13  print_r($arr);  //結果:Array ( [0] => -1 [1] => 0 [2] => 5 )  
14 } 
15 testArr($arr1); 
16 print_r($arr1);  //結果:Array ( [0] => -1 [1] => 5 [2] => 0 )  
17  
18 function testArr2(&$arr){ 
19  for($i=0;$i</count><count ($arr);$i++){ 
20   for($j=$i+1;$j<count($arr);$j++){ 
21    if($arr[$i]>$arr[$j]){ 
22     $temp = $arr[$i]; 
23     $arr[$i] = $arr[$j]; 
24     $arr[$j] = $temp; 
25    } 
26   } 
27  
28  } 
29 } 
30 testArr($arr1); 
31 print_r($arr1);  //結果:Array ( [0] => -1 [1] => 0 [2] => 5 )

三、對象數據類型傳值

class person{ 
 public $name; 
 public  $age; 
} 
 
$a = new person(); 
$a->name = '小明'; 
$a->age = '20'; 
//變量a在存的是對象的地址,把a賦給b這個變量,實際上就是賦了一個地址。 
$b = $a; 
$b->age = 30; 
//echo $a->age.$b->age;//結果是:30 30 
//給一個函數參數傳一個對象, 實際上傳的是這個對象的地址; 
function test($k){ 
 $k->age =40; 
} 
//調用 
test($b); 
//echo $a->age.$b->age;//結果是:40 40 

在PHP5中 對象的復制 是通過引用來實現的。上列中$a=new person; $b=$a; 其實等效於$a=new person; $b=&$a;
PHP5中默認就是通過引用來調用對象, 但有時你可能想建立一個對象的副本,並希望原來的對象的改變不影響到副本 . 為了這樣的目的,PHP定義了一個特殊的方法,稱為__clone.

 

4.php寫時拷貝

php中對於地址的指向(類似指針)功能不是由用戶自己來實現的,是由Zend核心實現的,php中引用采用的是“寫時拷貝”的原理,就是除非發生寫操作,指向同一個地址的變量或者對象是不會被拷貝的。

通俗的講
1:如果有下面的代碼

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

其實此時$a與$b都是指向同一內存地址而並不是$a與$b占用不同的內存

2:如果在上面的代碼基礎上再加上如下代碼

$a="EFG";

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

 

5.php引用於C指針的區別

在PHP 中引用的意思是:不同的名字訪問同一個變量內容.
與C語言中的指針是有差別的.C語言中的指針里面存儲的是變量的內容在內存中存放的地址。

PHP 的引用允許你用兩個變量來指向同一個內容

$a="ABC";
$b =&$a;
echo $a;//這里輸出:ABC
echo $b;//這里輸出:ABC
$b="EFG";
echo $a;//這里$a的值變為EFG 所以輸出EFG
echo $b;//這里輸出EFG

 當你 unset 一個引用,只是斷開了變量名和變量內容之間的綁定。這並不意味着變量內容被銷毀了。例如:

unset($a);
echo $b;//這里輸出EFG

  

6. ref:

  http://blog.sina.com.cn/s/blog_664c9f650101fl4b.html

  http://www.2cto.com/kf/201110/108970.html

  http://www.phpfensi.com/php/20140220/1612.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM