鍍金池/ 問(wèn)答/PHP  網(wǎng)絡(luò)安全/ PHP foreach()里使用& 引用賦值

PHP foreach()里使用& 引用賦值

<?php
$data = ['a','b','c'];

foreach ($data as &$v) {

}

foreach ($data as $v) {

}

unset($v);

var_dump($data);

這段代碼的結(jié)果如何推導(dǎo)?是什么原理?

回答
編輯回答
六扇門(mén)

好像以前見(jiàn)過(guò)類(lèi)似的問(wèn)題...

<?php
/* 第一次遍歷 */
$v = &$data[0];
$v = &$data[1];
$v = &$data[2];

// 第一次遍歷完成后, 這個(gè)時(shí)候 $v = &$data[2]


/* 第二輪遍歷 */
// 因?yàn)?v等價(jià)于$data[2],相當(dāng)于$data[2] = $data[0],把$data[2]賦值為a(即$data[0]); 此時(shí)數(shù)組array = ['a','b','a'];
$v = $data[0]; 

// 因?yàn)?v等價(jià)于$data[2],相當(dāng)于$data[2] = $data[1],把$data[2]賦值為b(即$data[1]); 此時(shí)數(shù)組array = ['a','b','b'];
$v = $data[1]; 

// 因?yàn)?v等價(jià)于$data[2],相當(dāng)于$data[2] = $data[2],即賦值為其本身,而此時(shí)已經(jīng)被上一次賦值為b; 此時(shí)數(shù)組array = ['a','b','b'];
$v = $data[2]; 

// 第二次遍歷完后, array = ['a','b','b']

unset($v); // unset($v)釋放掉臨時(shí)的引用

var_dump($data);

最后輸出:

array(3) {
  [0]=>
  string(1) "a"
  [1]=>
  string(1) "b"
  [2]=>
  string(1) "b"
}
2018年6月6日 06:15
編輯回答
拽很帥

這個(gè)經(jīng)典問(wèn)題鳥(niǎo)哥早就說(shuō)明過(guò)了,這里的一個(gè)點(diǎn)需要注意的是,第一次循環(huán)結(jié)束,$v是$data[2]的引用就可以了。
上面的答案講的都很好了,我這里只能來(lái)一份補(bǔ)充資料,從php源碼角度解析的php引用,給你網(wǎng)址吧:https://www.cnblogs.com/ohmyg...

2017年10月6日 05:48
編輯回答
尐潴豬

這個(gè)問(wèn)題好老啊,不過(guò)上面的大神解釋的很詳細(xì)。我對(duì)傳引用的理解就是引用和賦值的變量共用了一塊地址空間

2018年8月18日 19:36
編輯回答
傻叼

首先要明白foreach是一個(gè)不斷賦值的過(guò)程

第一輪循環(huán)實(shí)際是數(shù)組元素地址值的賦值,這并不會(huì)改變數(shù)組元素??聪旅孢@個(gè)簡(jiǎn)單實(shí)例:

$t = array();
$t[0] = 3;
$t[1] = 4;
$a = &$t[0];
$a = &$t[1];
echo $t[0]; // 數(shù)組第一個(gè)元素并沒(méi)有被改成4

開(kāi)始第二輪循環(huán)之前,并沒(méi)有銷(xiāo)毀$v這個(gè)指針變量,它其實(shí)是指向數(shù)組最后一個(gè)元素的。
循環(huán)第一次,$v='a',實(shí)際是將數(shù)組最后一個(gè)元素更改成'a',這個(gè)時(shí)候打印數(shù)組就是'a','b','a'
循環(huán)第二次,$v='b',實(shí)際是將數(shù)組最后一個(gè)元素更改成'b',這個(gè)時(shí)候打印數(shù)組就是'a','b','b'
循環(huán)第二次,$v='b',實(shí)際是將數(shù)組最后一個(gè)元素更改成'b',這個(gè)時(shí)候打印數(shù)組就是'a','b','b'
所以這就是數(shù)組最后的值。

2017年12月14日 14:17