Позавчера работая над статистикой для 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’.
Удачи!




test1.php:
function getmicrotime(){
list($usec, $sec) = explode(” “,microtime());
return ((float)$usec + (float)$sec);
}
$ar = array(
‘asdf’ => ‘asdf’,
‘jkl’ => array(
‘jfjf’ => 1e25,
234 => ‘dfksfdsj’,
‘xoxoxo’ => array(1,2,3,4,5,6,7,8,9,10),
),
‘fjfjfjdsfdfsfdsk’ => str_repeat(‘v’, 500),
);
for ($i = 0; $i < 100000; $i++) $r[] = $ar;
$t1 = getmicrotime();
foreach ($r as &$v);
$t2 = getmicrotime();
echo $t2 – $t1.”\n”;
echo memory_get_peak_usage(true).”\n”;
Второй файл test2.php точно такой же, но без амперсанда.
$ php test1.php
0.143193006516
32243712
$ php test2.php
0.0240671634674
5505024
$ php -v
PHP 5.2.8-pl2-gentoo (cli) (built: Jan 26 2009 12:35:28)
Вопрос — зачем оно нужно?