萬盛學電腦網

 萬盛學電腦網 >> 網絡編程 >> php編程 >> php中引用(變量和函數名前加&符號)用法

php中引用(變量和函數名前加&符號)用法

本文章來給大家介紹在php中我們常看到在在php變量前面加個&符號,這個就是php中引用符號了,它可以用於各種變量、函數、對象了下面我來給各位詳細介紹php&符號用法。

 

在 PHP 中引用意味著用不同的名字訪問同一個變量內容。這並不像 C 的指針,它們是符號表別名。注意在 PHP 中,變量名和變量內容是不一樣的,因此同樣的內容可以有不同的名字。PHP的引用是通過在變量名或者函數名前加&符號來實現的。下面解釋一下引用的幾種用法:

先來看官方法的說明


引用做什麼
PHP 的引用允許用兩個變量來指向同一個內容。意思是,當這樣做時:

<?php
$a =& $b;
?>
這意味著 $a 和 $b 指向了同一個變量。
Note:

$a 和 $b 在這裡是完全相同的,這並不是 $a 指向了 $b 或者相反,而是 $a 和 $b 指向了同一個地方。

 

Note:

如果具有引用的數組被拷貝,其值不會解除引用。對於數組傳值給函數也是如此。


Note:

如果對一個未定義的變量進行引用賦值、引用參數傳遞或引用返回,則會自動創建該變量。

Example #1 對未定義的變量使用引用

<?php
function foo(&$var) { }

foo($a); // $a is "created" and assigned to null

$b = array();
foo($b['b']);
var_dump(array_key_exists('b', $b)); // bool(true)

$c = new StdClass;
foo($c->d);
var_dump(property_exists($c, 'd')); // bool(true)
?>


同樣的語法可以用在函數中,它返回引用,以及用在 new 運算符中(PHP 4.0.4 以及以後版本):

<?php
$bar =& new fooclass();
$foo =& find_var($bar);
?>
自 PHP 5 起,new 自動返回引用,因此在此使用 =& 已經過時了並且會產生 E_STRICT 級別的消息。

Note:

不用 & 運算符導致對象生成了一個拷貝。如果在類中用 $this,它將作用於該類當前的實例。沒有用 & 的賦值將拷貝這個實例(例如對象)並且 $this 將作用於這個拷貝上,這並不總是想要的結果。由於性能和內存消耗的問題,通常只想工作在一個實例上面。

盡管可以用 @ 運算符來抑制構造函數中的任何錯誤信息,例如用 @new,但用 &new 語句時這不起效果。這是 Zend 引擎的一個限制並且會導致一個解析錯誤。

 

首先是變量的簡單引用,允許你用兩個變量來指向同一個內容,舉個簡單的例子:

<?php
$a = 5;
$b = &$a;
echo $b;
$a++;
echo $b;
?>
運行這段代碼是讓$b來引用$a的內容,然後改變$a的內容,$b的內容也會隨之變化。同樣的語法可以用在函數中,它返回引用,以及用在 new 運算符中:

<?php
$bar =& new fooclass();
$foo =& find_var ($bar);
?>
引用做的第二件事是用引用傳遞變量。這是通過在函數內建立一個本地變量,並且該變量在呼叫范圍內引用了同一個內容來實現的。說的通俗點就是一個函數的參數是一個本地變量的引用。下面再舉例說明一下

<?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
function &find_var ($param)
{
    /* ...code... */
    return $found_var;
}
$foo =& find_var ($bar);
$foo->x = 2;
?>
這個例子給$foo 賦值是函數find_var的返回引用,所以在給$foo->x賦值時就是給find_var的返回引用賦值,而不是簡單的賦值。
PHP引用的最後一個用法是引用定位,主要有兩個應用:一個是global 引用,當用 global $var 聲明一個變量時實際上建立了一個到全局變量的引用。也就是和$var =& $GLOBALS["var"];是一樣的。另外一個是$this的用法,在一個對象的方法中,$this 永遠是調用它的對象的引用。

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

<?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