Есть 2 программы. Чисто для теста, бессмысленные.
$a = array(1, 2, 3);
foreach ($a as &$row) {
$row = 2;
}
echo $a[1];
Здесь программа выведет 2, что и подразумевалось.
Теперь следующий код:
$a = array(1, 2, 3);
foreach ($a as $key => $row) {
$row = &$a[$key];
$row = 2;
}
echo $a[1];
Но он выведет 3. (но если заменить $row в теле цикла на другую переменную, то все будет ок).
Почему второй способ выводит 3 вместо 2?
И второй вопрос: как правильно понимать жесткие ссылки в PHP? Например, если записать $a = &$b, то это значит (как я понимаю), что переменная $a ссылается на значение, взятое из адреса $b (хотя тут про адреса не стоит наверное упоминать, ну да ладно). И при изменении любой из переменных, изменится значение адреса, поэтому и в $a, и в $b значения поменяются (типо синонимы). Но почему тогда при передаче в функцию по ссылке мы ставим перед параметром знак &? Пример: function check(&b) { //что-то делаем с переменной извне }; $a = 3; check($a);
Если расшифровать передачу аргумента, то получается, что мы передаем по ссылке вот что: &b = $a, но это, по идее, неправильно (синтаксис), однако работает. Если записать &b = $a в реальности, то интерпретатор выдаст ошибку, так как надо b = &$a. В том же С++ записывается именно первым способом (кроме записи указателей *), и поэтому там никаких вопросов передачи в функцию объектов нет. Или же запись &b в параметрах функции - это как исключение и нужно запомнить, что при этом b будет являться ссылкой на переданный параметр? В общем, просветите.
PHP
Почему выводит PHP именно так?
Любите вы задавать задачки на ночь)))
Первый вопрос, код 2.
Для ясности разберем итерациями:
1) $key = 0; $row = 1;
$row = & $a[0]; получили жесткую ссылку на первый элемент, там должно быть пока 1.
$row = 2; // мы в ячейку $a[0] поместили значение 2
2) $key = 1; $row = ...// а вот тут засада!!! смотрите итерацию 1. В $row к моменту присвоения очередного элемента массива имеем жесткую ссылку на $a[0]. Так вот, другими словами, при второй итерации мы имеем: $a[0] = $a[1]; то есть, в ячейку $a[0] мы поместили 2.
$row = & $a[1]; получили жесткую ссылку на второй элемент, там должно быть пока 2.
$row = 2; // в ячейку $a[1] поместили значение 2
3) $key = 2; $row = & $a[1] = $a[2] = 3. То есть, по ссылке в $row в ячейку $a[1] поместили значение $a[2], то есть 3.
$row = & $a[2]; разорвали ссылку на $a[1], создали ссылку на $a[2].
$row = 2; в ячейку $a[2] поместили 2.
конец.
В конце цикла мы имеем $a = [2,3,2], при этом на последний элемент ссылается переменная $row.
Какое решение? Достаточно в конце каждой итерации разрывать связь:
foreach ($a as $key => $row) {
$row = &$a[$key];
$row = 2;
unset($row);
}
Тогда на выходе имеем массив $a = [2, 2, 2];
Второй вопрос.
Много написано, но да ладно)
Жесткие ссылки правильно понимаете. $a и $b ссылаются на один объект zval. Присвоение значения любой переменной автоматически отразится на другой.
В случае обычной передачи аргумента в функцию и попытке изменить аргумент внутри функции, функция автоматически сделает копию аргумента и работает с ней, а оригинал останется нетронутым.
При передаче аргумента по ссылке, внутри функции мы можем менять значение аргумента. ПРи этом ничего не копируется и на выходе из функции в аргументе получим результат работы функции. Такой способ удобен при оперировании большими объемами значений, например, обработка буфера вывода перед выдачей на экран.
Первый вопрос, код 2.
Для ясности разберем итерациями:
1) $key = 0; $row = 1;
$row = & $a[0]; получили жесткую ссылку на первый элемент, там должно быть пока 1.
$row = 2; // мы в ячейку $a[0] поместили значение 2
2) $key = 1; $row = ...// а вот тут засада!!! смотрите итерацию 1. В $row к моменту присвоения очередного элемента массива имеем жесткую ссылку на $a[0]. Так вот, другими словами, при второй итерации мы имеем: $a[0] = $a[1]; то есть, в ячейку $a[0] мы поместили 2.
$row = & $a[1]; получили жесткую ссылку на второй элемент, там должно быть пока 2.
$row = 2; // в ячейку $a[1] поместили значение 2
3) $key = 2; $row = & $a[1] = $a[2] = 3. То есть, по ссылке в $row в ячейку $a[1] поместили значение $a[2], то есть 3.
$row = & $a[2]; разорвали ссылку на $a[1], создали ссылку на $a[2].
$row = 2; в ячейку $a[2] поместили 2.
конец.
В конце цикла мы имеем $a = [2,3,2], при этом на последний элемент ссылается переменная $row.
Какое решение? Достаточно в конце каждой итерации разрывать связь:
foreach ($a as $key => $row) {
$row = &$a[$key];
$row = 2;
unset($row);
}
Тогда на выходе имеем массив $a = [2, 2, 2];
Второй вопрос.
Много написано, но да ладно)
Жесткие ссылки правильно понимаете. $a и $b ссылаются на один объект zval. Присвоение значения любой переменной автоматически отразится на другой.
В случае обычной передачи аргумента в функцию и попытке изменить аргумент внутри функции, функция автоматически сделает копию аргумента и работает с ней, а оригинал останется нетронутым.
При передаче аргумента по ссылке, внутри функции мы можем менять значение аргумента. ПРи этом ничего не копируется и на выходе из функции в аргументе получим результат работы функции. Такой способ удобен при оперировании большими объемами значений, например, обработка буфера вывода перед выдачей на экран.
Зря вы через echo значение смотрите. Изменить код на:
$a = array(1,2,3,4,5);
foreach ($a as $key => $row) { $row = &$a[$key]; $row = 10; } var_dump($a);
И ужаснуться еще больше :)
Читать
http://php.net/manual/ru/language.references.whatare.php
http://php.net/manual/ru/language.references.arent.php
$a = array(1,2,3,4,5);
foreach ($a as $key => $row) { $row = &$a[$key]; $row = 10; } var_dump($a);
И ужаснуться еще больше :)
Читать
http://php.net/manual/ru/language.references.whatare.php
http://php.net/manual/ru/language.references.arent.php
Андрей Елесин
Я читал эти статьи. Но все равно не понимаю, почему так просходит. Не могли бы Вы мне помочь?
Ща еще почитаю пару... Ну тугодум я, простите :)
Ща еще почитаю пару... Ну тугодум я, простите :)
Похожие вопросы
- Почему на PHP пишутся сайты только для малого и среднего бизнеса, а для большого выбирают другой язык? Чем плох PHP?
- Почему обсирают PHP и PHP-ников?
- PHP Polling ChatGPT
- Как оптимизировать структуру сайта php. на готовом шаблоне
- Не работает PHP include на хостинге
- Хеширование пароля php
- Подскажите хороший курс по PHP практике?
- Пишу авторизацию (php). Куки не работают
- Вопрос начинающего программиста Python\PHP
- Как в PHP указать тип переменной unsigned int?
Про второе, что вы написали, я так и понимал, но вопрос был не в смысле передачи переменной по ссылке, а в том, почему это работает. Потому что все равно как-то странно то, что при обычном присвоении по ссылке мы ставим & после в PHP ($a = &$b), а в функции, цикле или где-нибудь еще как бы "до" ссылки (&$a, что по идее равно &$a = $b, но принимаем за $a = &$b). И при этом все работает. В общем, ясно-понятно)