亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > PHP > 正文

深入解析php中的foreach問題

2020-03-22 19:04:56
字體:
來源:轉載
供稿:網友
前言:
php4中引入了foreach結構,這是一種遍歷數組的簡單方式。相比傳統的for循環,foreach能夠更加便捷的獲取鍵值對。在php5之前,foreach僅能用于數組;php5之后,利用foreach還能遍歷對象(詳見:遍歷對象)。本文中僅討論遍歷數組的情況。

foreach雖然簡單,不過它可能會出現一些意外的行為,特別是代碼涉及引用的情況下。
下面列舉了幾種case,有助于我們進一步認清foreach的本質。
問題1:
復制代碼 代碼如下:
$arr = array(1,2,3);
foreach($arr as $k = &$v) {
$v = $v * 2;
}
// now $arr is array(2, 4, 6)
foreach($arr as $k = $v) {
echo "$k", " = ", "$v";
}

先從簡單的開始,如果我們嘗試運行上述代碼,就會發現最后輸出為0= 2 1= 4 2= 4 。
為何不是0= 2 1= 4 2= 6 ?
其實,我們可以認為 foreach($arr as $k = $v) 結構隱含了如下操作,分別將數組當前的'鍵'和當前的'值'賦給變量$k和$v。具體展開形如:
復制代碼 代碼如下:
foreach($arr as $k = $v){
//在用戶代碼執行之前隱含了2個賦值操作
$v = html' target='_blank'>currentVal();
$k = currentKey();
//繼續運行用戶代碼
……
}

根據上述理論,現在我們重新來分析下第一個foreach:
第1遍循環,由于$v是一個引用,因此$v = &$arr[0],$v=$v*2相當于$arr[0]*2,因此$arr變成2,2,3
第2遍循環,$v = &$arr[1],$arr變成2,4,3
第3遍循環,$v = &$arr[2],$arr變成2,4,6
隨后代碼進入了第二個foreach:
第1遍循環,隱含操作$v=$arr[0]被觸發,由于此時$v仍然是$arr[2]的引用,即相當于$arr[2]=$arr[0],$arr變成2,4,2
第2遍循環,$v=$arr[1],即$arr[2]=$arr[1],$arr變成2,4,4
第3遍循環,$v=$arr[2],即$arr[2]=$arr[2],$arr變成2,4,4
OK,分析完畢。
如何解決類似問題呢?php手冊上有一段提醒:
Warning : 數組最后一個元素的 $value 引用在 foreach 循環之后仍會保留。建議使用unset()來將其銷毀。
復制代碼 代碼如下:
$arr = array(1,2,3);
foreach($arr as $k = &$v) {
$v = $v * 2;
}
unset($v);
foreach($arr as $k = $v) {
echo "$k", " = ", "$v";
}
// 輸出 0= 2 1= 4 2= 6

從這個問題中我們可以看出,引用很有可能會伴隨副作用。如果不希望無意識的修改導致數組內容變更,最好及時unset掉這些引用。
問題2:
復制代碼 代碼如下:
$arr = array('a','b','c');
foreach($arr as $k = $v) {
echo key($arr), "= ", current($arr);
}
// 打印 1= b 1= b 1= b

這個問題更加詭異。按照手冊的說法,key和current分別是取數組中當前元素的的鍵值。
那為何key($arr)一直是1,current($arr)一直是b呢?
先用vld查看編譯之后的opcode:

我們從第3行的ASSIGN指令看起,它代表將array('a','b','c')賦值給$arr。
由于$arr為CV,array('a','b','c')為TMP,因此ASSIGN指令找到實際執行的函數為ZEND_ASSIGN_SPEC_CV_TMP_HANDLER。這里需要特別指出,CV是PHP5.1之后才增加的一種變量cache,它采用數組的形式來保存zval**,被cache住的變量再次使用時無需去查找active符號表,而是直接去CV數組中獲取,由于數組訪問速度遠超hash表,因而可以提高效率。
復制代碼 代碼如下:
static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_op *opline = EX(opline);
zend_free_op free_op2;
zval *value = _get_zval_ptr_tmp(&opline- op2, EX(Ts), &free_op2 TSRMLS_CC);

// CV數組中創建出$arr**指針
zval **variable_ptr_ptr = _get_zval_ptr_ptr_cv(&opline- op1, EX(Ts), BP_VAR_W TSRMLS_CC);
if (IS_CV == IS_VAR && !variable_ptr_ptr) {
……
}
else {
// 將array賦值給$arr
value = zend_assign_to_variable(variable_ptr_ptr, value, 1 TSRMLS_CC);
if (!RETURN_VALUE_UNUSED(&opline- result)) {
AI_SET_PTR(EX_T(opline- result.u.var).var, value);
PZVAL_LOCK(value);
}
}
ZEND_VM_NEXT_OPCODE();
}

ASSIGN指令完成之后,CV數組中被加入zval**指針,指針指向實際的array,這表示$arr已經被CV緩存了起來。

接下來執行數組的循環操作,我們來看FE_RESET指令,它對應的執行函數為ZEND_FE_RESET_SPEC_CV_HANDLER:
復制代碼 代碼如下:
static int ZEND_FASTCALL ZEND_FE_RESET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
……
if (……) {
……
} else {
// 通過CV數組獲取指向array的指針
array_ptr = _get_zval_ptr_cv(&opline- op1, EX(Ts), BP_VAR_R TSRMLS_CC);
……
}
……
// 將指向array的指針保存到zend_execute_data- Ts中(Ts用于存放代碼執行期的temp_variable)
AI_SET_PTR(EX_T(opline- result.u.var).var, array_ptr);
PZVAL_LOCK(array_ptr);
if (iter) {
……
} else if ((fe_ht = HASH_OF(array_ptr)) != NULL) {
// 重置數組內部指針
zend_hash_internal_pointer_reset(fe_ht);

鄭重聲明:本文版權歸原作者所有,轉載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯系我們修改或刪除,多謝。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
欧美激情精品久久久久久变态| 国产在线拍揄自揄视频不卡99| 国产日韩欧美自拍| 国产一区二区三区欧美| 亚洲香蕉在线观看| 欧美在线国产精品| 欧美另类极品videosbestfree| 欧美裸体xxxx极品少妇软件| 日韩毛片在线观看| 久久成年人免费电影| 国产精品视频999| 欧美精品一区二区三区国产精品| 欧美一区二区.| 国外成人免费在线播放| 国内揄拍国内精品| 精品亚洲一区二区三区四区五区| 日韩电影中文字幕在线| 久久九九免费视频| 久久久久久久久久久国产| 日韩免费在线观看视频| 热久久视久久精品18亚洲精品| 亚洲精品国产精品国自产观看浪潮| 日韩国产一区三区| 成人午夜在线视频一区| 九九精品在线播放| 最近2019中文字幕一页二页| 在线中文字幕日韩| 黄色成人在线播放| 国产成人精品在线播放| 国产免费成人av| 91精品在线影院| 欧美巨大黑人极品精男| 国产精品香蕉国产| 九九热精品视频国产| 亚洲欧洲成视频免费观看| xvideos亚洲| www.亚洲人.com| 久久久精品视频成人| 美女av一区二区| 日韩欧美在线免费观看| 欧美日韩国产一中文字不卡| 精品av在线播放| 久久综合电影一区| 精品国产一区二区三区久久| 国产精品久久久久久久久久新婚| 大桥未久av一区二区三区| 亚洲理论片在线观看| 777精品视频| 亚洲永久免费观看| 91在线免费网站| 国产精品海角社区在线观看| 欧美日韩成人精品| 2020久久国产精品| 欧美在线视频免费| 久久国产精品99国产精| 国模gogo一区二区大胆私拍| 高清在线视频日韩欧美| 欧美日韩成人黄色| 国产午夜精品一区理论片飘花| 欧美精品手机在线| 日韩在线播放av| 国产欧美日韩最新| 久久天堂电影网| 国内外成人免费激情在线视频网站| 色偷偷偷综合中文字幕;dd| 91久久精品日日躁夜夜躁国产| 国产97在线观看| 国产精品jizz在线观看麻豆| 欧美在线激情视频| 欧美老肥婆性猛交视频| 国产欧美日韩精品在线观看| 91av在线国产| 亚洲第一网站男人都懂| 亚洲视频第一页| 国产精品亚洲激情| 国产一区欧美二区三区| 精品中文字幕在线2019| 亚洲精品狠狠操| 2019最新中文字幕| 国产欧美日韩专区发布| 欧美在线www| 久久精品这里热有精品| 国产亚洲人成a一在线v站| 91天堂在线视频| 久久99久久99精品免观看粉嫩| 亚洲成色777777女色窝| 欧美精品电影免费在线观看| 日韩在线观看网址| 欧美巨乳美女视频| 亚洲日韩第一页| 国产色婷婷国产综合在线理论片a| 亚洲人成毛片在线播放| 不卡在线观看电视剧完整版| 91日本视频在线| 自拍偷拍亚洲精品| 欧美一级片久久久久久久| 久久精品国产视频| 亚洲日韩第一页| 国产在线精品自拍| 欧美日韩激情小视频| 欧美日韩人人澡狠狠躁视频| 日韩美女视频中文字幕| 国产精品高精视频免费| 国产在线播放不卡| 777国产偷窥盗摄精品视频| 91国产美女视频| 亚洲国产女人aaa毛片在线| 日韩高清欧美高清| 另类天堂视频在线观看| 欧美性xxxx极品hd欧美风情| 久久久在线免费观看| 日本成人黄色片| 欧美另类精品xxxx孕妇| 成人久久18免费网站图片| 欧美成人剧情片在线观看| 午夜精品久久久久久久99热浪潮| 色综合亚洲精品激情狠狠| 亚洲毛茸茸少妇高潮呻吟| 日韩av在线最新| 中文字幕亚洲一区二区三区五十路| 欧洲中文字幕国产精品| 中文国产成人精品久久一| 欧美一乱一性一交一视频| 国产精品久久久久久av下载红粉| 日本高清不卡在线| 国产精品久久久久久久久久东京| 日韩在线观看免费| 欧美猛男性生活免费| 17婷婷久久www| 日本久久久久亚洲中字幕| 欧美日本黄视频| 国产精品羞羞答答| 自拍偷拍亚洲精品| 欧美日韩成人免费| 亚洲成人黄色在线| 韩国精品久久久999| 日本亚洲精品在线观看| 九色成人免费视频| 91精品国产亚洲| 亚洲精品国产精品乱码不99按摩| 久久中文字幕国产| 欧美亚洲另类激情另类| 日韩美女中文字幕| 国产精品国产三级国产aⅴ9色| 亚洲欧美自拍一区| 日韩成人黄色av| 色综合久久中文字幕综合网小说| 中文字幕亚洲欧美在线| 欧美黄色三级网站| 成人福利在线视频| 在线观看国产成人av片| 欧美激情视频在线免费观看 欧美视频免费一| 精品国产老师黑色丝袜高跟鞋| 精品一区二区三区三区| 亚洲电影免费观看高清完整版在线观看| 亚洲xxx视频| 久久久久久久久久久免费精品| 久久69精品久久久久久国产越南| 亚洲综合在线小说| 国产99视频精品免视看7| 久久精品精品电影网| 91人成网站www| 久久精品成人动漫| 日韩在线视频一区|