- PHP面試一戰(zhàn)到底
- 閆小坤
- 1013字
- 2022-07-28 19:21:36
3.1 變量引用
首先看一道題目:
代碼如下:(源碼文件:ch03/reference_1.php)
$a = 1; $b = & $a; $b = 2; var_dump($a);
這時$a的輸出結(jié)果是什么?
答案為2。
除第1行為$a賦值外,沒有再對$a有任何操作,但$a的值由1變?yōu)?。
這就是本節(jié)要討論的變量引用。
3.1.1 指針與引用
在C語言里,指針是一個強(qiáng)大的存在,它可以通過傳遞指針的方式,將一個變量或函數(shù)的內(nèi)存地址傳遞出去。直接操作內(nèi)存是一個高效行為,但過于危險和不可控制,所以在一些語言,如Java、PHP等,不允許直接傳遞指針,而采用變量引用的方式來實(shí)現(xiàn)。
PHP的變量引用,是指不同的變量訪問同一變量的內(nèi)容,語法為&+變量名。例如上例的第2行代碼,將$a的引用賦值給$b,即$a和$b指向同一個“地址”,當(dāng)任何一個變量變化時,都會影響到另一個變量。圖3-1中的refcount表示該“地址”被引用的次數(shù)。

圖3-1 refcount“地址”被引用的次數(shù)
3.1.2 引用的取消
設(shè)置一個引用變量之后,可以用unset來取消其引用,即銷毀引用變量。
程序代碼如下:(源碼文件:ch03/reference_2.php)
$a = 1; $b = & $a; unset($a); var_dump($b); //output 1
如圖3-2所示。

圖3-2 變量的引用
可以看到,unset($a)之后,內(nèi)存中的地址并沒有釋放,而只是將refcount減1,所以$b的值仍然是1。
3.1.3 forech的引用陷阱
經(jīng)常有這樣的場景:某個數(shù)組需要遍歷來修改某個值,改完之后需要進(jìn)行第二次遍歷。請看以下程序示例:(源碼文件:ch03/reference_foreach.php)

第1個foreach的作用是將數(shù)組的每個元素都加1,所以$nums = [2,3]。
第2個foreach的預(yù)期是輸出2,3,但為什么輸出了2,2呢?
請看圖3-3所示。

圖3-3 foreach的輸出
結(jié)合上圖,我們分析一下為什么出現(xiàn)這種情況。
第2行,定義的數(shù)組[1,2],如圖3-3所示的第1步。
第3至5行,將數(shù)組的每個元素都加1,所以$nums = [2,3],同時數(shù)組的第2個元素引入了$num的引用。這造成了后面的意想不到的情況。
第2個foreach處理第1個元素時,$num被賦值為2,同時$num又和第2個元素共享地址,所以第2個元素的值由3變?yōu)?。
第2個foreach處理第2個元素時,$num被賦值為2,同時$num又和第2個元素共享地址,相當(dāng)于把變量本身的值重新賦值給自己,所以第2個元素的值仍然為2。
綜上所述,$nums變?yōu)榱薣2,2]。
究其原因,是由于數(shù)組最后一個元素的$num引用在foreach循環(huán)之后仍會保留。建議使用unset()來將其銷毀。
規(guī)避的方法有三種:
方法1:不使用變量引用,而用$nums[$index]取出要改變的元素。
(源碼文件:ch03/reference_foreach_fix_1.php)

方法2:既然第1個和第2個foreach的變量名相等,那么不妨將第2個foreach的變量更名為$num2,就規(guī)避了變量引用的問題,也能輸出正確的結(jié)果。
程序代碼如下:(源碼文件:ch03/reference_foreach_fix_2.php)

方法3:unset調(diào)引用變量。
程序代碼如下:(源碼文件:ch03/reference_foreach_fix_3.php)

另外,還有一種使用函數(shù)式編程的解決方案,將在第5章講解。
- 嵌入式軟件系統(tǒng)測試:基于形式化方法的自動化測試解決方案
- Android和PHP開發(fā)最佳實(shí)踐(第2版)
- Expert Data Visualization
- Learning Probabilistic Graphical Models in R
- Rust游戲開發(fā)實(shí)戰(zhàn)
- Python網(wǎng)絡(luò)爬蟲技術(shù)與應(yīng)用
- Building Dynamics CRM 2015 Dashboards with Power BI
- 從Power BI到Analysis Services:企業(yè)級數(shù)據(jù)分析實(shí)戰(zhàn)
- 計算機(jī)應(yīng)用基礎(chǔ)(第二版)
- Arduino電子設(shè)計實(shí)戰(zhàn)指南:零基礎(chǔ)篇
- Mastering Embedded Linux Programming
- Visual Basic程序設(shè)計基礎(chǔ)
- Solr權(quán)威指南(下卷)
- 深入理解Kafka:核心設(shè)計與實(shí)踐原理
- Learning Cocos2d-JS Game Development