Модераторы: skyboy, MoLeX, Aliance, ksnk
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Проблема с foreach($arr as &$val){...}, нелогично работает foreach 
V
    Опции темы
Drkwv
Дата 6.7.2007, 15:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 21.3.2006

Репутация: нет
Всего: нет



Код

  $ARGS=array(1,2,3);
  echo('<pre>');
  print_r($ARGS);
  foreach($ARGS as &$val)$val=$val;
  print_r($ARGS);
  foreach($ARGS as $val)echo($val);
  echo('</pre>');

Получаю в ответ:
Код
    
Array
(
[0] => 1
[1] => 2
[2] => 3
)
Array
(
[0] => 1
[1] => 2
[2] => 3
)
122


Вопрос - почему 122, а не 123? reset($ARGS) не помогает, а в print_r все нормально отображается. В чем причина такого поведения foreach?

Добавлено через 6 минут и 21 секунду
Тему можно снести  smile прошу прощения.
PM MAIL   Вверх
Warpkid
Дата 26.11.2010, 18:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 49
Регистрация: 26.4.2008

Репутация: 3
Всего: 3



==

Это сообщение отредактировал(а) Warpkid - 26.11.2010, 18:55
PM MAIL   Вверх
ksnk
Дата 26.11.2010, 19:23 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Цитата(Drkwv @  6.7.2007,  15:22 Найти цитируемый пост)
Тему можно снести

От это поведение php станет логичнее?  smile 

Причина в кривизне рук реализаторов foreach'а. Они не чистят предыдущее значение-сылку, а сразу начинают присваивать переменной значение из цикла. Непонятно, впрочем, почему не 121 получилось? 

Лечение семантическое - не нужно использовать одинаковые идентификаторы для циклов для переменных ссылок и переменных - значений.

Более дорогое решение - завести дополнительную переменную и устанавливать после цикла на нее адрес переменной цикла. впрочем это все где-то на странице обсуждения foreach есть...


--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
skyboy
Дата 26.11.2010, 20:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


неОпытный
****


Профиль
Группа: Модератор
Сообщений: 9820
Регистрация: 18.5.2006
Где: Днепропетровск

Репутация: 75
Всего: 260



рекомендую читать ман, хотя бы в момент возникновения проблемы  smile 
Цитата(php.net/foreach)

Warning
Reference of a $value and the last array element remain even after the foreach loop. It is recommended to destroy it by unset().

естественно, твой код выдает именно такой результат.
после первого цикла имя $val указывает туда же, куда и $ARGS[2].
потом, во втором цикле, в $val(соответственно, и в $ARGS[2]) записывается поочередно 1, затем 2. и когда подходит время перебора к третьему элементу, там как раз значение "2".
впрочем, судя по 
Цитата(Drkwv @  6.7.2007,  14:22 Найти цитируемый пост)
Тему можно снести

ты уже и сам разобрался.
разобрался бы ещё быстрее, запустив такой код:
Код

$ARGS = array(1,2,3,4);
foreach($ARGS as &$val) $val = $val;
foreach($ARGS as $val) print_r($ARGS);

и получив:
Цитата

1 2 3 1
1 2 3 2
1 2 3 3
1 2 3 3


Добавлено @ 20:15
Цитата(ksnk @  26.11.2010,  18:23 Найти цитируемый пост)
Причина в кривизне рук реализаторов foreach'а

так работает reference. это не то же самое, что ссылки в С++.
единственное "шаманство", которое могли бы добавить разработчики - принудительный  unset переменной-контейнера, как они сами в мане и рекомендуют делать. но тогда за пределами цикла не было бы даже потенциальной возможности обработать $val. что было бы неприятно при преждевременном выходе по break. или даже без break - надо было бы при помощи дополнительных операций получать последний элемент. который в текущей реализации - на блюдечке преподносится.
PM MAIL   Вверх
ksnk
Дата 26.11.2010, 23:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


прохожий
****


Профиль
Группа: Комодератор
Сообщений: 6855
Регистрация: 13.4.2007
Где: СПб

Репутация: 96
Всего: 386



Цитата(skyboy @  26.11.2010,  20:11 Найти цитируемый пост)
единственное "шаманство", которое могли бы добавить разработчики - принудительный  unset переменной-контейнера...

Ну дык сбрасывать можно было бы не в конце цикла, а в начале следующего. Причем лучше бы это делали именно сами zend'ы. Я не думаю, что кто-то теперешним  малопредсказуемым свойством переменных-указателей пользуется. А вот использование адреса элемента цикла снаружи цикла - вещь иногда полезная. 
Цитата(skyboy @  26.11.2010,  20:11 Найти цитируемый пост)
так работает reference.

 smile imho, это называется баг... 





--------------------
Человеку свойственно ошибаться, программисту свойственно ошибаться профессионально ! user posted image
PM MAIL WWW Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "PHP"
Aliance
IZ@TOP
skyboy
SamDark
MoLeX

Новичкам:

  • PHP редакторы собираются и обсуждаются здесь
  • Электронные книги по PHP, документацию можно найти здесь
  • Интерпретатор PHP, полную документацию можно скачать на PHP.NET

Важно:

  • Не брезгуйте пользоваться тегами [code=php]КОД[/code] для повышения читабельности текста/кода.
  • Перед созданием новой темы воспользуйтесь поиском и загляните в FAQ
  • Действия модераторов можно обсудить здесь

Внимание:

  • Темы "ищу скрипт", "подскажите скрипт" и т.п. будут переноситься в форум "Web-технологии"
  • Темы с именами: "Срочно", "помогите", "не знаю как делать" будут УДАЛЯТЬСЯ

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, IZ@TOP, skyboy, SamDark, MoLeX, awers.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | PHP: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0973 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.