Странное поведение Foreach

<?php $a = array('a', 'b', 'c', 'd'); foreach ($a as &$v) { } foreach ($a as $v) { } print_r($a); ?> 

Я думаю, что это обычная программа, но это результат, который я получаю:

 Array ( [0] => a [1] => b [2] => c [3] => c ) 

Может кто-нибудь, пожалуйста, объясните мне это?

Это хорошо документированное поведение PHP. См. Предупреждение на странице foreach php.net.

Предупреждение

Ссылка на значение $ и последний элемент массива остаются даже после цикла foreach . Рекомендуется уничтожить его unset ().

 $a = array('a', 'b', 'c', 'd'); foreach ($a as &$v) { } unset($v); foreach ($a as $v) { } print_r($a); с $a = array('a', 'b', 'c', 'd'); foreach ($a as &$v) { } unset($v); foreach ($a as $v) { } print_r($a); 

РЕДАКТИРОВАТЬ

Попытайтесь пошаговое руководство к тому, что на самом деле происходит здесь

 $a = array('a', 'b', 'c', 'd'); foreach ($a as &$v) { } // 1st iteration $v is a reference to $a[0] ('a') foreach ($a as &$v) { } // 2nd iteration $v is a reference to $a[1] ('b') foreach ($a as &$v) { } // 3rd iteration $v is a reference to $a[2] ('c') foreach ($a as &$v) { } // 4th iteration $v is a reference to $a[3] ('d') // At the end of the foreach loop, // $v is still a reference to $a[3] ('d') foreach ($a as $v) { } // 1st iteration $v (still a reference to $a[3]) // is set to a value of $a[0] ('a'). // Because it is a reference to $a[3], // it sets $a[3] to 'a'. foreach ($a as $v) { } // 2nd iteration $v (still a reference to $a[3]) // is set to a value of $a[1] ('b'). // Because it is a reference to $a[3], // it sets $a[3] to 'b'. foreach ($a as $v) { } // 3rd iteration $v (still a reference to $a[3]) // is set to a value of $a[2] ('c'). // Because it is a reference to $a[3], // it sets $a[3] to 'c'. foreach ($a as $v) { } // 4th iteration $v (still a reference to $a[3]) // is set to a value of $a[3] ('c' since // the last iteration). // Because it is a reference to $a[3], // it sets $a[3] to 'c'. 

Первый цикл foreach не производит никаких изменений в массиве, как и ожидалось. Тем не менее, это заставляет $v присваивать ссылку на каждый из элементов $a , так что к моменту окончания первого цикла $v является, по сути, ссылкой на $a[2] .

Как только начинается второй цикл, $v теперь присваивается значение каждого элемента. Однако $v уже является ссылкой на $a[2]; поэтому любое присвоенное ему значение будет автоматически скопировано в последний элемент массива!

Таким образом, во время первой итерации $a[2] станет нулевым, тогда один, а затем снова будет эффективно скопирован на себя. Чтобы решить эту проблему, вы всегда должны отключать переменные, которые вы используете в своих байтах by-reference foreach, или, еще лучше, избегать использования прежнего вообще.