答案是1。为什么呢?通过vld查看这段代码的opcodes可以知道答案:
root@lmt:/var/www# php -dvld.active=1 test.php
filename: /var/www/test.php
function name: (null)
number of ops: 16
compiled vars: !0 = $arr, !1 = $v
line # * op fetch ext return operands
---------------------------------------------------------------------------------
9 0 > INIT_ARRAY ~0 1 //初始化数组,并付给临时变量~0
1 ASSIGN !0, ~0 //将$arr赋值给临时变量,这就是普通函数参数传值
10 2 > FE_RESET $2 !0, ->13 //初始化数组指针,开始循环
3 > > FE_FETCH $3 $2, ->13
4 > ZEND_OP_DATA
5 ASSIGN !1, $3
12 6 IS_EQUAL ~5 !1, 1
7 > JMPZ ~5, ->11
8 > ZEND_ASSIGN_DIM !0
9 ZEND_OP_DATA 2, $7
10 > JMP ->11
13 11 > ECHO !1
14 12 > JMP ->3 //一次循环结束跳转到3,这是还是使用最初赋值的临时变量~0,所以无法循环到新加进来的第二个元素
13 > SWITCH_FREE $2
18 14 ECHO ' '
15 > RETURN 1
简单来说就是因为foreach中传的是$arr的副本,并且foreach循环每次都使用最初那个副本进行循环。
如果输出12的效果该怎么做呢?
通过opcodes可以看到原因:
root@lmt:/var/www# php -dvld.active=1 test.php
compiled vars: !0 = $arr, !1 = $key, !2 = $v
line # * op fetch ext return operands
---------------------------------------------------------------------------------
9 0 > INIT_ARRAY ~0 1
1 ASSIGN !0, ~0
10 2 > SEND_REF !0
3 DO_FCALL 1 $2 'each'
4 FETCH_DIM_R $3 $2, 1
5 ASSIGN !2, $3
6 FETCH_DIM_R $5 $2, 0
7 ASSIGN !1, $5
8 > JMPZ $2, ->16
12 9 > IS_EQUAL ~7 !2, 1
10 > JMPZ ~7, ->14
11 > ZEND_ASSIGN_DIM !0
12 ZEND_OP_DATA 2, $9
13 > JMP ->14
13 14 > ECHO !2
14 15 > JMP ->2
18 16 > ECHO ' '
17 > RETURN 1
使用each循环的时候每次传入的是$arr的引用,所以每次在循环内部的改变能影响下一
次的循环。