[ Поиск ] - [ Пользователи ] - [ Календарь ]
Полная Версия: Ссылочный синтаксис foreach-"затирание" переменных
Страницы: 1, 2
ПАХОМ
Здравствуйте!

Пожалуйста, поясните что значит "затирается"

Пример.

<?php ## Изменение элементов при переборе.
$numbers = array(100, 313, 605);
foreach ($numbers as &$v) $v++;
echo "Элементы массива: ";
foreach ($numbers as $elt) echo "$elt ";
?>

Комментарий автора книги.
Ссылочная переменная $v— это полноценная жесткая ссылка, которая не уничтожается после завершения работы цикла foreach! Таким образом, если вы попытаетесь что-то присвоить переменной $v в конце программы, изменения затронут последний элемент массива $numbers — ведь именно он соответствовал $v на последней итерации цикла!
Как раз по этой причине мы используем переменную $elt, а не все ту же $v, в последнем цикле вывода листинга: иначе бы последний элемент массива $numbers, которому соответствует жесткая ссылка $v, "затирался" при последующей итерации по массиву.

С уважением,
Василий.
jetistyum
$numbers = array(100, 313, 605); 
foreach ($numbers as &$v) $v++;


В этом варианте у тебя переменная $v содержит в себе ссылку на ту часть массива, с которой ты работаешь в данной итерации, тоесть
при первом проходе $v = (ячейка памяти в которой хранится первый элемент массива $numbers ) тоесть если из нее прочитать - получишь 100, а если ты в нее запишешь, например $v = 200, то это изменит первый элемент массива, и после этой итерации массив станет равен 200, 313, 605

Во втором примере у тебя не ссылка на ячейку памяти, а копия содержания, тоесть создается отдельная переменная в отдельном месте памяти, и присваивается значение 100, если ты ей присвоишь другое значение, "пострадает" переменная, но первоначальный массив останется не измененным.
ПАХОМ
Первая часть кода выводит
606 101 314 314

Вторая часть выводит
Элементы массива: 101 314 606

Я попробую переформулировать вопрос: почему первая часть кода выводит четыре значения, ведь массив содержит только три значения. И по какой причине два последних значения одинаковые?

С уважением,
Василий.
Игорь_Vasinsky
в жизни не юзал ссылки, просто в начале перепрыгнул их - не понял нафиг они нужны.

С глубочайшим уважением, Моя персона.

_____________
HTML, CSS (Bootstrap), JS(JQuery, ExtJS), PHP, MySQL, MSSql, Posgres, (TSql, BI OLAP, MDX), Mongo, Git, SVN, CodeIgnater, Symfony, Yii 2, JiRA, Redmine, Bitbucket, Composer, Rabbit MQ, Amazon (SQS, S3, Transcribe), Docker
ПАХОМ
Стоп! Прошу прощения, я код не тот прикрепил ... сори
Вот то что надо



<?php. ## Первая часть кода, которая выводит 606 101 314 314
$numbers1 = array(100, 313, 605);
foreach ($numbers1 as &$v) $v++;
echo ""Элементы массива: $v ";
foreach (
$numbers1 as $v) echo "$v ";
?>
<?php ## Вторая часть кода, которая выводит 101 314 606

$numbers = array(100, 313, 605);
foreach (
$numbers as &$v) $v++;
echo ""Элементы массива: "
;
foreach ($numbers as $elt) echo "$elt ";
?>

ПАХОМ
Блин, я по ходу уже сам свою мазню увидел ...
Четыре символа, поскольку в первом коде надо написать
echo ""Элементы массива: ";
вместо
echo ""Элементы массива: $v ";

А вот по какой причине третий элемент не 606, а 314 в первом коде, пока не понял.

ПС: прошу не серчать, первый раз сталкиваюсь PHP.
jetistyum
что=то ты намудрил :)


Вот код, который явно тебе покажет разницу между двумя методами. А описание почему так - читай в первом моем посте\


<?php
## Первая часть кода, которая выводит 101 314 606
$numbers1 = array(100, 313, 605);
foreach ($numbers1 as &$v) {
$v++;
echo "Элементы массива: $v ";
}
var_dump($numbers1); //дамп всего массива после того как по нему прошелся цикл

## Первая часть кода, которая выводит 101 314 606 но при этом сам массив останется не измененным.

$numbers2 = array(100, 313, 605);
foreach ($numbers2 as $d) {
$d++;
echo "Элементы массива: $d ";
}
var_dump($numbers2); //дамп всего массива после того как по нему прошелся цикл


?>
ПАХОМ
У Вас в обоих случаях вывод корректный.
Я не понял ... можно словами объяснить?
ПАХОМ
Цитата
Как раз по этой причине мы используем переменную $elt, а не все ту же $v, в последнем цикле вывода листинга: иначе бы последний элемент массива $numbers, которому соответствует жесткая ссылка $v, "затирался" при последующей итерации по массиву.

Вот часть объяснения, которое я не понимаю. Что значит затирается? И зачем надо использовать новую переменную?
jetistyum
дело в том, что код, который ты представил в обоих случаях не корректный
(цикл foreach заканчивается раньше чем вывод, после <?php стоит точка, что вообще не дает выполнить код., не корректно расставлены кавычки, что не выведет вообще строки. Поэтому просто скопируй свои листинг, тот, который конкретно у тебя, который работает.


В моем случае (как и должно быть по идее в твоем ) вывод одинаковый, однако посмотри на состояние массива 1 после цикла, и на состояние массива 2 после цикла. в этом вся разница.

Цитата
Вот часть объяснения, которое я не понимаю. Что значит затирается? И зачем надо использовать новую переменную?


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

предположим (очень грубо)

ячейка памяти 01 в ней хранится ПЕРВЫЙ элемент твоего массива, тоесть число 100, ячейка 02 содержит второй элемент, тоесть 313, ячейка 03 - третий элемент - 605

так вот по ссылке переменная $v каждый раз соответствует этой ячейке...

(Это понятно?)

соответственно в последний свой проход в переменной остается ссылка на последний элемент массива, тоесть переменная $v будет равняться ячейке №03 в которой число 605
после окончания первого цикла переменная никуда не пропала, и соответственно значение ее осталось
если ты будешь использовать ее во втором цикле (но уже без ссылки) то в таком случае в нее будет скопировано значение элемента массива

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


Как подробнее объяснить, я уже не представляю smile.gif
ПАХОМ
Так ... буду впитывать :)
Вот код откорректированный и дополненный комментариями:

<?php ## Работа со ссылками № 1
echo "Вот массив, с которым работают оба кода: 100, 313, 605 <br>";
$numbers1 = array(100, 313, 605);
foreach ($numbers1 as &$v) $v++;
echo "Вот что получается: ";
foreach ($numbers1 as $v) echo "<br> $v";
var_dump($numbers1); //дамп всего массива после того как по нему прошелся цикл
?>

<?php
## Работа со ссылками № 2
$numbers = array(100, 313, 605);
foreach ($numbers as &$v) $v++;
echo "<br> Вот что получается: ";
foreach ($numbers as $elt) echo "<br> $elt";
var_dump($numbers); //дамп всего массива после того как по нему прошелся цикл
?>
jetistyum
почитай внимательно все что я писал, я все описал, что тут происходит, хоть и немного на другом примере .
ПАХОМ
Цитата
предположим (очень грубо)

  • ячейка памяти 01 в ней хранится ПЕРВЫЙ элемент твоего массива, тоесть число 100,
  • ячейка 02 содержит второй элемент, тоесть 313,
  • ячейка 03 - третий элемент - 605

так вот по ссылке переменная $v каждый раз соответствует этой ячейке...
(Это понятно?)

Да, это понятно.
Цитата

  • соответственно в последний свой проход в переменной остается ссылка на последний элемент массива, тоесть переменная $v будет равняться ячейке №03 в которой число 605
  • после окончания первого цикла переменная никуда не пропала, и соответственно значение ее осталось
    если ты будешь использовать ее во втором цикле (но уже без ссылки) то в таком случае в нее будет скопировано значение элемента массива

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

И вот где собака зарыта: при выводе третьего элемента массива - 606, он "затирается" не первым элементом массива (101), а вторым - 314.
jetistyum
Цитата
Т.е. наличие амперсанда изменяет уже сам массив, а не только ссылку на него.




Вкратце

$a = 10; (создалась в памяти новая "ячейка" в которую записалось значение 10)
$b = &$a; (создалась ссылка на $a, новое место в памяти не выделялось, теперь если изменишь значение $a, изменится и значение $b, и наоборот)

$c = $a; (создалась новая ячейка памяти, в нее записалось значение переменной $a на момент выражения, тоесть 10, если в дальнейшем $a изменитя, это никак не повлияет на $c, и наоборот, изменения в $c никак не затронут $a, это два сами-по-себе живущих переменные)
jetistyum
Цитата (ПАХОМ @ 11.11.2012 - 11:50)
И вот где собака зарыта: при выводе третьего элемента массива - 606, он "затирается" не первым элементом массива (101), а вторым - 314.


Я этого в коде, приведенном тобой не замечаю, более того во втором цикле переменная-ссылка &$v инициализируется повторно в foreach и не затирает первый массив, вопреки тому что я думал. Может разница в версиях php.
либо ты опять тестируешь не на том коде, который у тебя в листинге приведён.
Быстрый ответ:

 Графические смайлики |  Показывать подпись
Здесь расположена полная версия этой страницы.
Invision Power Board © 2001-2024 Invision Power Services, Inc.