Позавчера работая над статистикой для UMapper‘a наткнулся на странный баг, который (как выяснилось сегодня) я совсем не понял. Совпадения случаются, и вот сегодня читая PHP5 Zend Certification Guide, наткнулся на объяснение. Сначала код:
1 2 3 4 5 6 | $vars = array('a', 'b', 'c'); foreach ($vars as &$v); foreach ($vars as $v); print_r($vars); |
Как вы думаете, каков будет результат выполнения приведенного кода? А вот такой:
1 2 3 4 5 | Array( [0] => a [1] => b [2] => b ) |
Если ответили правильно – зачет, если же нет – читайте объяснение, так как это не баг.
На самом деле все довольно просто: внутри первого цикла, только на первый взгляд ничего не происходит, на самом деле создается ссылка $v, и далее при каждой итерации ссылка указывает на текущий элемент массива. Таким образом после окончания цикла $v = &$vars[2], т.е. переменная $v является ссылкой на последний элемент массива. Во втором цикле, переменная $v при каждой итерации получает значение текущего элемента, а так как переменная является ссылкой обновляется и $vars[2]:
1-я итерация: $v = $vars[0]; => $vars[2] = $vars[0]; // $vars[2] = ‘a’
2-я итерация: $v = $vars[1]; => $vars[2] = $vars[1]; // $vars[2] = ‘b’
3-я итерация: $v = $vars[2]; => $vars[2] = $vars[2]; // $vars[2] = ‘b’ – так как на момент присваивания значение $vars[2] было измененно предыдущей итерацией на ‘b’.
Удачи!


