這篇文章主要介紹“PHP中引用的概念是什么”,在日常操作中,相信很多人在PHP中引用的概念是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”PHP中引用的概念是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
創(chuàng)新互聯專注于企業(yè)營銷型網站建設、網站重做改版、武清網站定制設計、自適應品牌網站建設、H5技術、商城網站制作、集團公司官網建設、外貿網站建設、高端網站制作、響應式網頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為武清等各大城市提供網站開發(fā)制作服務。
之前我們其實已經有過幾篇文章講過引用方面的問題,這次我們來全面的梳理一下引用在PHP到底是怎么回事,它和C中的指針有什么不同,在使用的時候要注意些什么。
在 PHP 中引用意味著用不同的名字訪問同一個變量內容。它不是C的指針,保存的并不是內存地址,無法進行指針運算。引用只是符號表的別名。就像 Unix 系統中的硬鏈接, Windows 系統中的快捷方式。
上面是官方手冊中的原文,怎么說呢,引用其實和我們印象中的C里面的指針并不是相同的概念。指針是針對真實內存的操作,引用是針對指向這個內存的符號表的操作。還是從操作系統的快捷方式來說,快捷方式是可以刪的,這就是PHP的引用。而C不僅刪了快捷方式,還把原文件也給刪了,這就是C的指針操作。
// 引用不是指針
$a = 1;
$b = &$a;
echo $a, '===', $b, PHP_EOL;
unset($b);
echo $a, '===', $b, PHP_EOL;
上面的代碼是在PHP中,我們把$b變量指向$a,作為$a的引用變量。然后刪除$b,對$a沒有任何影響。
#include
#include
int main()
{
// C 中的指針和引用
int a = 1;
int* b = &a;
printf("%i\n", a); // 1
free(b); // free b
printf("%i\n", a); //get error: *** error for object 0x7fff6350da08: pointer being freed was not allocated
return 0;
}
而C中的引用指針就不行了,我們把b變量刪掉后,再打印a變量就直接報錯了。
雖然說PHP的底層也是C寫得,但我們都知道C中的指針是出了名的變態(tài),沒有一定的功底非常容易出錯。所以PHP的開發(fā)者沒有暴露C的原始指針能力,而是采用了和Java之類的類似的引用能力。這也是現代語言的特性,不需要我們過多的關注過于底層的能力,而將更多的時間放在業(yè)務實現上。
如果具有引用的數組被拷貝,其值不會解除引用。對于數組傳值給函數也是如此。
$arr1 = ["a", "b"];
$t1 = &$arr1[1];
$arr2 = $arr1;
$arr2[1] = "c";
var_dump($arr1);
// array(2) {
// [0]=>
// string(1) "a"
// [1]=>
// &string(1) "c"
// }
$arr1 = ["a", "b"];
$t1 = &$arr1[1];
unset($t1); // unset 掉引用
$arr2 = $arr1;
$arr2[1] = "c";
var_dump($arr1);
// array(2) {
// [0]=>
// string(1) "a"
// [1]=>
// string(1) "b"
// }
這個其實挺有意思的,我們對比這兩個例子可以看出一個問題,$t變量指向$arr[1]的引用。$arr2直接=這個$arr1,沒有使用引用,然后$arr2修改了$arr2[1]的內容,$arr1相應的內容也發(fā)生了改變,如果unset掉$t變量,則$arr1相應的內容就不會發(fā)生改變。對此,我在文檔中找到了下面的解釋:
由于PHP內部工作的特殊性,如果對數組的單個元素進行引用,然后復制數組,無論是通過賦值還是通過函數調用中的值傳遞,都會將引用復制為數組的一部分。這意味著對任一數組中任何此類元素的更改都將在另一個數組(和其他引用中)中重復,即使數組具有不同的作用域(例如,一個是函數內部的參數,另一個是全局的)!在復制時沒有引用的元素,以及在復制數組后分配給其他元素的引用,將正常工作(即獨立于其他數組)。
不僅僅是數組,對象的引用也會有一些好玩的問題。
$o1 = new stdClass();
$o1->a = 'a';
var_dump($o1);
// object(stdClass)#1 (1) {
// ["a"]=>
// string(1) "a"
// }
$o2 = &$o1;
$o3 = $o1;
$o2->a = 'aa';
var_dump($o1);
// object(stdClass)#1 (1) {
// ["a"]=>
// string(2) "aa"
// }
var_dump($o3); // $o2修改了$a為'aa',$o3也變成了'aa'
// object(stdClass)#1 (1) {
// ["a"]=>
// string(2) "aa"
// }
$o1->a = 'aaa';
$o1 = null;
var_dump($o2); // $o2引用變成了null
// NULL
var_dump($o3); // $o3不僅引用還存在,并且$a變成了'aaa'
// object(stdClass)#1 (1) {
// ["a"]=>
// string(3) "aaa"
// }
上面例子中有三個對象,$o1、$o2、$o3,其中,$o2是對$o1的引用,$o3是直接賦值為$o1。對$o2屬性的操作不僅會反映在$o1中,也會反映到$o3中。其實我們之前專門有一篇文章就講的這個問題,首先對象默認賦值就是引用,其次這個例子很好地證明了引用就是一個符號表的綁定。刪除了快捷方式對原始對象和其他快捷方式沒有任何影響。大家可以參考:對象賦值在PHP中到底是不是引用?
關于引用在方法參數上的傳遞,最重要的是記住兩點:一是方法內部修改了變量外部也會變,這是引用的特性嘛;二是只能傳遞變量、New 語句、從函數中返回的引用三種類型。
error_reporting(E_ALL);
function foo(&$var)
{
$var++;
echo 'foo:', $var;
}
function bar() // Note the missing &
{
$a = 5;
return $a;
}
foo(bar()); // 自 PHP 5.0.5 起導致致命錯誤,自 PHP 5.1.1 起導致嚴格模式錯誤
// 自 PHP 7.0 起導致 notice 信息,Notice: Only variables should be passed by reference
foo($a = 5); // 表達式,不是變量, Notice: Only variables should be passed by reference
// foo(5); // 導致致命錯誤 !5是個常量!
///////////////////////////////
// 正確的傳遞類型
$a = 5;
foo($a); // 變量
function &baz()
{
$a = 5;
return $a;
}
foo(baz()); // 從函數中返回的引用
function foo1(&$var)
{
print_r($var);
}
foo1(new stdClass()); // new 表達式
引用的返回并不是經常使用的一個能力。文檔中的原文是:不要用返回引用來增加性能,引擎足夠聰明來自己進行優(yōu)化。僅在有合理的技術原因時才返回引用!
$a = 1;
function &test(){
global $a;
return $a;
}
$b = &test($a);
$b = 2;
echo $a, PHP_EOL;
當你想要返回一個引用變量的時候,一定要給方法定義和方法調用的時候都使用&符號。這個是需要注意的點。當其他地方修改原本的變量值或者返回的變量值經過修改后,都會影響到所有調用這個值的地方。所以說,引用的返回是比較危險的,因為你不清楚什么時候在什么地方這個值可能發(fā)生了修改,對于bug的排查會非常困難。
取消引用其實就是直接unset掉變量就可以了。但是一定要記住,PHP中的引用是指向的符號表,對原始真實的值是不起作用的,所以即使unset掉了最原始的那個變量,對其它引用賦值的變量也不會有影響?。?/p>
$a = 1;
$b = &$a;
$c = &$b;
$b = 2;
echo '定義引用后:', $a, '===', $b, '===', $c, PHP_EOL;
unset($b);
$b = 3;
echo '取消$b的引用,不影響$a、$c:', $a, '===', $b, '===', $c, PHP_EOL;
$b = &$a;
unset($a);
echo '取消$a,不影響$b、$c:', $a, '===', $b, '===', $c, PHP_EOL;
// 定義引用后:2===2===2
// 取消$b的引用:2===3===2
// 取消$a,不影響$c:===3===2
$a = 1;
$b = & $a;
$c = & $b; // $a, $b, $c reference the same content '1'
$a = NULL; // All variables $a, $b or $c are unset
echo '所有引用成空:', $a, '===', $b, '===', $c, PHP_EOL;
這一次算是比較徹底的把引用說了個透。關于PHP的引用只要記住了它的定義就非常好理解了,最直觀的就是當成是操作系統的快捷方式就好了,并沒有我們想象中的那么難,和C的指針相比真的只是娃娃級別,多多練習多多復習自然就能很好地掌握使用啦!
測試代碼:https://github.com/zhangyue0503/dev-blog/blob/master/php/202002/source/%E5%BD%BB%E5%BA%95%E6%90%9E%E6%98%8E%E7%99%BDPHP%E7%9A%84%E4%B8%AD%E5%BC%95%E7%94%A8%E7%9A%84%E6%A6%82%E5%BF%B5.php
參考文檔:https://www.php.net/manual/zh/language.references.whatare.phphttps://www.php.net/manual/zh/language.references.whatdo.phphttps://www.php.net/manual/zh/language.references.arent.phphttps://www.php.net/manual/zh/language.references.pass.phphttps://www.php.net/manual/zh/language.references.return.phphttps://www.php.net/manual/zh/language.references.unset.phphttps://www.php.net/manual/zh/language.references.spot.php
到此,關于“PHP中引用的概念是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續(xù)學習更多相關知識,請繼續(xù)關注創(chuàng)新互聯網站,小編會繼續(xù)努力為大家?guī)砀鄬嵱玫奈恼拢?/p>
文章題目:PHP中引用的概念是什么
網頁URL:http://weahome.cn/article/jieocd.html