Почему выводит PHP именно так? - Вопросы по сайтостроению

Вопрос Почему выводит PHP именно так?

Регистрация
12 Окт 2013
Сообщения
87
Репутация
0
Спасибо
0
Монет
0
Есть 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 будет являться ссылкой на переданный параметр? В общем, просветите.
 
Регистрация
29 Июн 2013
Сообщения
107
Репутация
0
Спасибо
0
Монет
0
Любите вы задавать задачки на ночь))) Первый вопрос, код 2. Для ясности разберем итерациями: 1) $key = 0; $row = 1; $row = &(int) 1; // такая запись говорит, что мы ссылаемся на zval, куда ссылается элемент $a[0] // а там ($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. Присвоение к любой переменной автоматически отразится на другой. Какой смысл передача в функцию аргумента по явной ссылке, то есть с использованием &? Главный смысл в том, что в этом случае, внутри функции мы можем менять значение аргумента. В случае прямой передаче и попытке изменить значение аргумента, функция автоматически сделает копию и работает с ней, а оригинал останется нетронутым. Такой способ удобен при оперировании большими объемами значений, например, обработка буфера вывода перед выдачей на экран.
 
Сверху Снизу