萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> php編程 >> PHP引用傳遞與引用&一些用法介紹

PHP引用傳遞與引用&一些用法介紹

在php中引用是使用&來做,下面我來給大家介紹在php引用一些用法與引用問題與事項實例,歡迎各位朋友進入參考。

引用是什麼

在 PHP 中引用意味著用不同的名字訪問同一個變量內容。這並不像 C 的指針,替代的是,引用是符號表別名。注意在 PHP 中,變量名和變量內容是不一樣的,因此同樣的內容可以有不同的名字。最接近的比喻是 Unix 的文件名和文件本身——變量名是目錄條目,而變量內容則是文件本身。引用可以被看作是 Unix 文件系統中的 hardlink。

引用做什麼
PHP 的引用允許用兩個變量來指向同一個內容。
當 $a =& $b; 時 $a 和 $b 指向了同一個變量。
提示:$a 和 $b 在這裡是完全相同的,這並不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一個地方。

可以將一個變量通過引用傳遞給函數,這樣該函數就可以修改其參數的值。語法如下:

 代碼如下 復制代碼

<?php
function foo(&$var)
{
    $var++;
}
 
$a=5;
foo($a);
echo $a;

// 輸出的是:6


PHP引用符&

關於php的引用(就是在變量或者函數、對象等前面加上&符號)的作用,我們先看下面這個程序。

 代碼如下 復制代碼

   
<?php
$a = 100; //聲明變量a
$b = &$a; //聲明變量b,引用自變量a
echo "$a <br />"; 
echo "$b <br />";
$a++; //變量a自增1
echo "$a <br />";
echo "$b <br />";//查看變量b,也增加了1,說明使用的是同一存儲單元
?>

程序運行結果:

100
100
101
101

很多人誤解php中的引用跟C當中的指針一樣,事實上並非如此,而且很大差別。C語言中的指針除了在數組傳遞過程中不用顯式申明外,其他都需要使用*進行定義,而php中對於地址的指向(類似指針)功能不是由用戶自己來實現的,是由Zend核心實現的,php中引用采用的是“寫時拷貝”的原理,就是除非發生寫操作,指向同一個地址的變量或者對象是不會被拷貝的。

php默認為傳值傳遞:

 代碼如下 復制代碼

 
<?php   
$a = 20;
$b = $a;
$a = $a + 10;
echo $a.' and '.$b;
?>

程序運行結果:

30 and 20

要是想變為地址傳遞需要加&,既:

 代碼如下 復制代碼

 
<?php
$a = 20;
$b = &$a;
$a = $a + 10;
echo $a.' and '.$b;
?>

程序運行結果:

就是說,&把$a的地址傳給了$b,這樣的話這兩個變量現在共享一個內存的存儲區域,就是說它們的值是一樣的。

同樣的語法可以用在函數中,它返回引用,以及用在 new 運算符中:

 代碼如下 復制代碼

view sourceprint?
1 <?php 

2 $bar =& new fooclass(); 

3 $foo =& find_var($bar); 

4 ?>

引用做的第二件事是用引用傳遞變量。這是通過在函數內建立一個本地變量,並且該變量在呼叫范圍內引用了同一個內容來實現的。說的通俗點就是一個函數的參數是一個本地變量的引用。下面再舉例說明一下:

 代碼如下 復制代碼

<?php
function foo(&$val1, $val2) {
 $val1 += 1;
 $val2 += 1;
}
$a=5;
$b=10;
foo($a,$b);
echo $a;
echo $b;
?>

運行這段代碼是給函數傳遞兩個參數,一個是引用$a的內容,一個是$b的值,在執行此函數後,發現$a的內容改變了,而$b的內容則沒有變化。


PHP引用以及誤區


PHP中的引用可以理解成變量的別名。由於PHP的變量名是存儲在符號表(symbol table)中的,變量內容是存儲在堆中,引用就是用符號表中的不同符號(symbol)名稱來訪問同一存儲內容,和Unix文件系統中的hardlink是同一個概念,比如:

 代碼如下 復制代碼

<?php
$a = 1;
$b = &$a; //$a與$b指向同一內容
$b = 2;
echo $b; //2
echo $a; //2
傳遞引用
引用傳遞很簡單,就是一個「&」符號,比如:

<?php
function foo(&$a) {
  $a = 2;
}

$b = 1;
foo($b);
echo $b; //2

返回引用
大多數情況下並不需要返回引用來提高性能,zend引擎會自己進行優化,但是如果你非得返回引用得話,可以按照以下方式來返回引用:

 代碼如下 復制代碼

<?php
class foo {
    public $value = 42;

    public function &getValue() { // 需要一個"&"
        return $this->value;
    }
}

$obj = new foo;
$myValue = &$obj->getValue(); // 還需要一個"&",$myValue是對class foo中的$value的引用
$obj->value = 2;              // 修改對象的$value屬性
echo $myValue;                // 輸出2,$myValue與class foo中的$value值相同

與指針的區別
引用與指針很像,但是其並不是指針,看如下的代碼:

 代碼如下 復制代碼 <?php
    $a = 0;
    $b = &a;
    echo $a; //0
    unset($b);
    echo $a; //0

由於$b只是$a的別名,所以即使$b被釋放了,$a沒有任何影響,但是指針可不是這樣的,看如下代碼:

 代碼如下 復制代碼

#include <stdio.h>
int main(int argc, char const *argv[]) {
    int a = 0;
    int* b = &a;

    printf("%in", a); //0
    free(b);
    printf("%in", a); //*** error for object 0x7fff6350da08: pointer being freed was not allocated
}

由於b是指向a的指針,所以釋放了b的內存之後,再訪問a就會出現錯誤,比較明顯的說明了PHP引用與C指針的區別。

對象與引用
在PHP中使用對象的時候,大家總是被告知“對象是按照引用傳遞的”,其實這是個誤區。PHP的對象變量存儲的是此對象的一個標示符,在傳遞對象的時候,其實傳遞的就是這個標示符,而並不是引用,看如下代碼:

 代碼如下 復制代碼

<?php
$a = new A;
$b = $a;   
$b->testA = 2;

/*
 * 此時$a,$b的關系:
 *        +-----------+      +-----------------+
 * $a --> | object id | ---> | object(Class A) |
 *        +-----------+      +-----------------+
 *                               ^
 *        +-----------+          |
 * $b --> | object id | ---------+
 *        +-----------+   
 *
 *
 */

$c = new B;
$a = $c;
$a->testB = "Changed Class B";

/*
 * 此時$a,$b,$c的關系:
 *        +-----------+      +-----------------+
 * $b --> | object id | ---> | object(Class A) |
 *        +-----------+      +-----------------+
 *                              
 *        +------------+         
 * $a --> | object id2 | -------------+
 *        +------------+              |
 *                                    v
 *        +------------+      +-----------------+
 * $c --> | object id2 | ---> | object(Class B) |
 *        +------------+      +-----------------+
 */

echo "object a: "; var_dump($a); //["testB"]=> string(15) "Changed Class B"
echo "object b: "; var_dump($b); //["testA"] => int(2)
echo "object c: "; var_dump($c); //["testB"]=> string(15) "Changed Class B"

如果對象是按照引用傳遞的,那麼$a, $b, $c輸出的內容應該一樣,事實上結果並非如此。 看下面通過引用傳遞對象的列子:

 代碼如下 復制代碼

<?php
$aa = new A;
$bb = &$aa;  // 引用
$bb->testA = 2;

/*
 * 此時$aa, $bb的關系:
 *
 *         +-----------+      +-----------------+
 * $bb --> | object id | ---> | object(Class A) |
 *         +-----------+      +-----------------+
 *              ^                 
 *              |
 * $aa ---------+
 *
 *
 */

$cc = new B;
$aa = $cc;
$aa->testB = "Changed Class B";

/*
 * 此時$aa, $bb, $cc的關系:
 *
 *         +-----------+      +-----------------+
 *         | object id | ---> | object(Class A) |
 *         +-----------+      +-----------------+
 *             
 * $bb ---->-----+     
 *               |
 * $aa ---->-----+
 *               | 
 *               v  
 *         +------------+     
 *         | object id2 | --------------+
 *         +------------+               |
 *                                      v
 *         +------------+      +-----------------+
 * $cc --> | object id2 | ---> | object(Class B) |
 *         +------------+      +-----------------+
 */

echo "object aa: "; var_dump($aa); //["testB"]=>string(15) "Changed Class B"
echo "object bb: "; var_dump($bb); //["testB"]=>string(15) "Changed Class B"
echo "object cc: "; var_dump($cc); //["testB"]=>string(15) "Changed Class B"

此時$aa,$bb,$cc三者內容完全一樣,所以可以看出對象並不是按照引用傳遞,要盡快走出這個誤區。

copyright © 萬盛學電腦網 all rights reserved