Как на самом деле работает PHP 'foreach'?



позвольте мне префикс этого, сказав, что я знаю, что foreach есть, делает и как его использовать. Этот вопрос касается того, как он работает под капотом, и я не хочу никаких ответов по строкам "вот как вы зацикливаете массив с foreach".





долгое время я предполагал, что foreach работал с самим массивом. Потом я нашел много ссылок на то, что он работает с скопировать массива, и с тех пор я предположил, что это конец история. Но недавно я вступил в дискуссию по этому вопросу, и после небольшого эксперимента обнаружил, что это не было на самом деле 100% верно.



позвольте мне показать, что я имею в виду. Для следующих тестовых случаев мы будем работать со следующим массивом:



$array = array(1, 2, 3, 4, 5);


тестовый случай 1:



foreach ($array as $item) {
echo "$itemn";
$array[] = $item;
}
print_r($array);

/* Output in loop: 1 2 3 4 5
$array after loop: 1 2 3 4 5 1 2 3 4 5 */


это ясно показывает, что мы не работаем напрямую с различными источника - в противном случае цикл будет продолжаться вечно, так как мы постоянно толкают элементы массива в цикле. Но просто чтобы убедиться, что это так:



тестовый случай 2:



foreach ($array as $key => $item) {
$array[$key + 1] = $item + 2;
echo "$itemn";
}

print_r($array);

/* Output in loop: 1 2 3 4 5
$array after loop: 1 3 4 5 6 7 */


это подтверждает наш первоначальный вывод, мы работаем с копией исходного массива во время цикла, иначе мы бы увидели измененные значения во время цикла. но...



если мы посмотрим в руководство, мы находим такое заявление:




когда по каждому элементу первой начинает выполняться, внутренний указатель массива автоматически устанавливается на первый элемент массива.




право... это, кажется, предполагает, что foreach полагается на указатель массива источник. Но мы только что доказали, что мы не работает с исходным массивом, да? Ну, не совсем так.



тестовый случай 3:



// Move the array pointer on one to make sure it doesn't affect the loop
var_dump(each($array));

foreach ($array as $item) {
echo "$itemn";
}

var_dump(each($array));

/* Output
array(4) {
[1]=>
int(1)
["value"]=>
int(1)
[0]=>
int(0)
["key"]=>
int(0)
}
1
2
3
4
5
bool(false)
*/


Итак, несмотря на то, что мы не работаем непосредственно с исходным массивом, мы работаем непосредственно с указателем исходного массива-тот факт, что указатель находится в конце массива в конце цикла показывает это. Но это не может быть правдой - если так, то тестовый случай 1 будет бесконечный цикл.



в руководстве PHP также говорится:




как foreach опирается на внутренний указатель массива, его изменение внутри цикла может привести к непредсказуемому поведению.




Ну, давайте выясним, что такое "неожиданное поведение" (технически, любое поведение является неожиданным, так как я больше не знаю, чего ожидать).



тестовый случай 4:



foreach ($array as $key => $item) {
echo "$itemn";
each($array);
}

/* Output: 1 2 3 4 5 */


тестовый случай 5:



foreach ($array as $key => $item) {
echo "$itemn";
reset($array);
}

/* Output: 1 2 3 4 5 */


...ничего неожиданного там нет, на самом деле это, кажется, поддерживает теорию "копии источника".





Вопрос



что здесь происходит? Мой C-fu недостаточно хорош для меня, чтобы извлечь правильный вывод просто путем глядя на исходный код PHP, я был бы признателен, если бы кто-то мог перевести его на английский язык для меня.



мне кажется, что foreach работает с скопировать массива, но устанавливает указатель массива-источника в конец массива после цикла.




  • правильно ли это и вся история?

  • если нет, то что он на самом деле делает?

  • есть ли ситуация, когда с помощью функций, которые регулируют массив указатель (each(),reset() и соавт.) во время foreach может повлиять на исход цикла?

857   0  

Comments

    Ничего не найдено.