Здравствуйте!
Пожалуйста, поясните что значит "затирается"
Пример.
<?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
10.11.2012 - 23:38
$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
10.11.2012 - 23:48
в жизни не юзал ссылки, просто в начале перепрыгнул их - не понял нафиг они нужны.
С глубочайшим уважением, Моя персона.
_____________
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.
$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
11.11.2012 - 00:25
что=то ты намудрил :)
Вот код, который явно тебе покажет разницу между двумя методами. А описание почему так - читай в первом моем посте\
<?php
$numbers1 = array(100, 313, 605);
foreach ($numbers1 as &$v) {
$v++;
echo "Элементы массива: $v ";
}
var_dump($numbers1);
$numbers2 = array(100, 313, 605);
foreach ($numbers2 as $d) {
$d++;
echo "Элементы массива: $d ";
}
var_dump($numbers2);
?>
У Вас в обоих случаях вывод корректный.
Я не понял ... можно словами объяснить?
Цитата |
Как раз по этой причине мы используем переменную $elt, а не все ту же $v, в последнем цикле вывода листинга: иначе бы последний элемент массива $numbers, которому соответствует жесткая ссылка $v, "затирался" при последующей итерации по массиву.
|
Вот часть объяснения, которое я не понимаю. Что значит затирается? И зачем надо использовать новую переменную?
jetistyum
11.11.2012 - 01:00
дело в том, что код, который ты представил в обоих случаях не корректный
(цикл foreach заканчивается раньше чем вывод, после <?php стоит точка, что вообще не дает выполнить код., не корректно расставлены кавычки, что не выведет вообще строки. Поэтому просто скопируй свои листинг, тот, который конкретно у тебя, который работает.
В моем случае (как и должно быть по идее в твоем ) вывод одинаковый, однако посмотри на состояние массива 1 после цикла, и на состояние массива 2 после цикла. в этом вся разница.
Цитата |
Вот часть объяснения, которое я не понимаю. Что значит затирается? И зачем надо использовать новую переменную? |
Когда ты перебираешь массив по ссылке (твой первый случай ) в каждую итерацию цикла переменной присваивается ссылка на ячейку памяти, где хранится элемент массива
предположим (очень грубо)
ячейка памяти 01 в ней хранится ПЕРВЫЙ элемент твоего массива, тоесть число 100, ячейка 02 содержит второй элемент, тоесть 313, ячейка 03 - третий элемент - 605
так вот по ссылке переменная $v каждый раз соответствует этой ячейке...
(Это понятно?)
соответственно в последний свой проход в переменной остается ссылка на последний элемент массива, тоесть переменная $v будет равняться ячейке №03 в которой число 605
после окончания первого цикла переменная никуда не пропала, и соответственно значение ее осталось
если ты будешь использовать ее во втором цикле (но уже без ссылки) то в таком случае в нее будет скопировано значение элемента массива
а так как переменная с первого раза осталась ссылочная, то в ячейку номер 03 скопируется значение первого элемента массива, и первоначальное значение 605 "затрется" новым значением.
Как подробнее объяснить, я уже не представляю
Так ... буду впитывать :)
Вот код откорректированный и дополненный комментариями:
<?php
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
$numbers = array(100, 313, 605);
foreach ($numbers as &$v) $v++;
echo "<br> Вот что получается: ";
foreach ($numbers as $elt) echo "<br> $elt";
var_dump($numbers);
?>
jetistyum
11.11.2012 - 01:57
почитай внимательно все что я писал, я все описал, что тут происходит, хоть и немного на другом примере .
Цитата |
предположим (очень грубо)
- ячейка памяти 01 в ней хранится ПЕРВЫЙ элемент твоего массива, тоесть число 100,
- ячейка 02 содержит второй элемент, тоесть 313,
- ячейка 03 - третий элемент - 605
так вот по ссылке переменная $v каждый раз соответствует этой ячейке... (Это понятно?) |
Да, это понятно.
Цитата |
- соответственно в последний свой проход в переменной остается ссылка на последний элемент массива, тоесть переменная $v будет равняться ячейке №03 в которой число 605
- после окончания первого цикла переменная никуда не пропала, и соответственно значение ее осталось
если ты будешь использовать ее во втором цикле (но уже без ссылки) то в таком случае в нее будет скопировано значение элемента массива
|
Т.е. наличие амперсанда изменяет уже сам массив, а не только ссылку на него.
Цитата |
а так как переменная с первого раза осталась ссылочная, то в ячейку номер 03 скопируется значение первого элемента массива, и первоначальное значение 605 "затрется" новым значением. |
И вот где собака зарыта: при выводе третьего элемента массива - 606, он "затирается" не первым элементом массива (101), а вторым - 314.
jetistyum
11.11.2012 - 23:30
Цитата |
Т.е. наличие амперсанда изменяет уже сам массив, а не только ссылку на него.
|
Вкратце
$a = 10; (создалась в памяти новая "ячейка" в которую записалось значение 10)
$b = &$a; (создалась ссылка на $a, новое место в памяти не выделялось, теперь если изменишь значение $a, изменится и значение $b, и наоборот)
$c = $a; (создалась новая ячейка памяти, в нее записалось значение переменной $a на момент выражения, тоесть 10, если в дальнейшем $a изменитя, это никак не повлияет на $c, и наоборот, изменения в $c никак не затронут $a, это два сами-по-себе живущих переменные)
jetistyum
11.11.2012 - 23:39
Цитата (ПАХОМ @ 11.11.2012 - 11:50) |
И вот где собака зарыта: при выводе третьего элемента массива - 606, он "затирается" не первым элементом массива (101), а вторым - 314. |
Я этого в коде, приведенном тобой не замечаю, более того во втором цикле переменная-ссылка &$v инициализируется повторно в foreach и не затирает первый массив, вопреки тому что я думал. Может разница в версиях php.
либо ты опять тестируешь не на том коде, который у тебя в листинге приведён.
Быстрый ответ:
Powered by dgreen
Здесь расположена полная версия этой страницы.