這篇文章將為大家詳細講解有關PHP中引用計數(shù)指的是什么意思,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

創(chuàng)新互聯(lián)公司服務項目包括平壩網(wǎng)站建設、平壩網(wǎng)站制作、平壩網(wǎng)頁制作以及平壩網(wǎng)絡營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,平壩網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務的客戶以成都為中心已經(jīng)輻射到平壩省份的部分城市,未來相信會繼續(xù)擴大服務區(qū)域并繼續(xù)獲得客戶的支持與信任!
php,一個嵌套的縮寫名稱,是英文超級文本預處理語言(PHP:Hypertext Preprocessor)的縮寫。PHP 是一種 HTML 內(nèi)嵌式的語言,PHP與微軟的ASP頗有幾分相似,都是一種在服務器端執(zhí)行的嵌入HTML文檔的腳本語言,語言的風格有類似于C語言,現(xiàn)在被很多的網(wǎng)站編程人員廣泛的運用。
在PHP的數(shù)據(jù)結(jié)構(gòu)中,引用計數(shù)就是指每一個變量,除了保存了它們的類型和值之外,還額外保存了兩個內(nèi)容,一個是當前這個變量是否被引用,另一個是引用的次數(shù)。為什么要多保存這樣兩個內(nèi)容呢?當然是為了垃圾回收(GC)。
也就是說,當引用次數(shù)為0的時候,這個變量就沒有再被使用了,就可以通過 GC 來進行回收,釋放占用的內(nèi)存資源。
任何程序都不能無限制的一直占用著內(nèi)存資源,過大的內(nèi)存占用往往會帶來一個嚴重的問題,那就是內(nèi)存泄露,而 GC 就是PHP底層自動幫我們完成了內(nèi)存的銷毀,而不用像 C 一樣必須去手動地 free 。
我們需要安裝 xdebug 擴展,然后使用 xdebug_debug_zval() 函數(shù)就可以看到指定內(nèi)存的詳細信息了,比如:
$a = "I am a String";
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'從上述內(nèi)容中可以看出,這個 $a 變量的內(nèi)容是 I am a String 這樣一個字符串。而括號中的 refcount 就是引用次數(shù),is_ref 則是說明這個變量是否被引用。我們通過變量賦值來看看這個兩個參數(shù)是如何變化的。
$b = $a;
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=0)='I am a String'
$b = &$a;
xdebug_debug_zval('a');
// a: (refcount=2, is_ref=1)='I am a String'當我們進行普通賦值后,refcount 和 is_ref 沒有任何變化,但當我們進行引用賦值后,可以看到 refcount 變成了2,is_ref 變成了1。這也就是說明當前的 \$a 變量被引用賦值了,它的內(nèi)存符號表服務于 $a 和 $b 兩個變量。
$c = &$a;
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String'
unset($c, $b);
xdebug_debug_zval('a');
// a: (refcount=1, is_ref=1)='I am a String'
$b = &$a;
$c = &$a;
$b = "I am a String new";
xdebug_debug_zval('a');
// a: (refcount=3, is_ref=1)='I am a String new'
unset($a);
xdebug_debug_zval('a');
// a: no such symbol繼續(xù)增加一個 $c 的引用賦值,可以看到 refcount 會繼續(xù)增加。然后 unset 掉 $b 和 $c 之后,refcount 恢復到了1,不過這時需要注意的是,is_ref 依然還是1,也就是說,這個變量被引用過,這個 is_ref 就會變成1,即使引用的變量都已經(jīng) unset 掉了這個值依然不變。
最后我們 unset 掉 $a ,顯示的就是 no such symbol 了。當前變量已經(jīng)被銷毀不是一個可以用的符號引用了。(注意,PHP中的變量對應的是內(nèi)存的符號表,并不是真正的內(nèi)存地址)
和普通類型的變量一樣,對象變量也是使用同樣的計數(shù)規(guī)則。
// 對象引用計數(shù)
class A{
}
$objA = new A();
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A { }
$objB = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=2, is_ref=0)=class A { }
$objC = $objA;
xdebug_debug_zval('objA');
// objA: (refcount=3, is_ref=0)=class A { }
unset($objB);
class C{
}
$objC = new C;
xdebug_debug_zval('objA');
// objA: (refcount=1, is_ref=0)=class A { }不過這里需要注意的是,對象的符號表是建立的連接,也就是說,對 $objC 進行重新實例化或者修改為 NULL ,并不會影響 $objA 的內(nèi)容,這方面的知識我們在之前的 對象賦值在PHP中到底是不是引用? 文章中已經(jīng)有過說明。對象進行普通賦值操作也是引用類型的符號表賦值,所以我們不需要加 & 符號。
// 數(shù)組引用計數(shù)
$arrA = [
'a'=>1,
'b'=>2,
];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
// 'a' => (refcount=0, is_ref=0)=1,
// 'b' => (refcount=0, is_ref=0)=2
// )
$arrB = $arrA;
$arrC = $arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=4, is_ref=0)=array (
// 'a' => (refcount=0, is_ref=0)=1,
// 'b' => (refcount=0, is_ref=0)=2
// )
unset($arrB);
$arrC = ['c'=>3];
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=0)=array (
// 'a' => (refcount=0, is_ref=0)=1,
// 'b' => (refcount=0, is_ref=0)=2
// )
// 添加一個已經(jīng)存在的元素
$arrA['c'] = &$arrA['a'];
xdebug_debug_zval('arrA');
// arrA: (refcount=1, is_ref=0)=array (
// 'a' => (refcount=2, is_ref=1)=1,
// 'b' => (refcount=0, is_ref=0)=2,
// 'c' => (refcount=2, is_ref=1)=1
// )調(diào)試數(shù)組的時候,我們會發(fā)現(xiàn)兩個比較有意思的事情。
一是數(shù)組內(nèi)部的每個元素又有單獨的自己的引用計數(shù)。這也比較好理解,每一個數(shù)組元素都可以看做是一個單獨的變量,但數(shù)組就是這堆變量的一個哈希集合。如果在對象中有成員變量的話,也是一樣的效果。當數(shù)組中的某一個元素被 & 引用賦值給其他變量之后,這個元素的 refcount 會增加,不會影響整個數(shù)組的 refcount 。
二是數(shù)組默認上來的 refcount 是2。其實這是 PHP7 之后的一種新的特性,當數(shù)組定義并初始化后,會將這個數(shù)組轉(zhuǎn)變成一個不可變數(shù)組(immutable array)。為了和普通數(shù)組區(qū)分開,這種數(shù)組的 refcount 是從2開始起步的。當我們修改一下這個數(shù)組中的任何元素后,這個數(shù)組就會變回普通數(shù)組,也就是 refcount 會變回1。這個大家可以自己嘗試下,關于為什么要這樣做的問題,官方的解釋是為了效率,具體的原理可能還是需要深挖 PHP7 的源碼才能知曉。
其實 PHP 在底層已經(jīng)幫我們做好了 GC 機制就不需要太關心變量的銷毀釋放問題,但是,千萬要注意的是對象或數(shù)組中的元素是可以賦值為自身的,也就是說,給某個元素賦值一個自身的引用就變成了循環(huán)引用。那么這個對象就基本不太可能會被 GC 自動銷毀了。
// 對象循環(huán)引用
class D{
public $d;
}
$d = new D;
$d->d = $d;
xdebug_debug_zval('d');
// d: (refcount=2, is_ref=0)=class D {
// public $d = (refcount=2, is_ref=0)=...
// }
// 數(shù)組循環(huán)引用
$arrA['arrA'] = &$arrA;
xdebug_debug_zval('arrA');
// arrA: (refcount=2, is_ref=1)=array (
// 'a' => (refcount=0, is_ref=0)=1,
// 'b' => (refcount=0, is_ref=0)=2,
// 'arrA' => (refcount=2, is_ref=1)=...
// )不管是對象還是數(shù)組,在打印調(diào)試時出現(xiàn)了 ... 這樣的省略號,那么你的程序中就出現(xiàn)了循環(huán)引用。在之前的文章 關于PHP中對象復制的那點事兒 中我們也講過這個循環(huán)引用的問題,所以這個問題應該是我們在日常開發(fā)中應該時刻關注的問題。
關于“PHP中引用計數(shù)指的是什么意思”這篇文章就分享到這里了,希望以上內(nèi)容可以對大家有一定的幫助,使各位可以學到更多知識,如果覺得文章不錯,請把它分享出去讓更多的人看到。
本文標題:PHP中引用計數(shù)指的是什么意思
當前URL:http://chinadenli.net/article38/jiggpp.html
成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供、全網(wǎng)營銷推廣、商城網(wǎng)站、網(wǎng)站改版、企業(yè)建站、動態(tài)網(wǎng)站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)