Есть следующий PHP код:
<?php
function func(&$r) {
$r++;
}
$r = 1;
func(func($r));
echo $r;
?>
и он выдает 2.
И такой код:
<?php
function func(&$r) {
$r++;
}
$r = 1;
func($r);
echo $r;
?>
Также выдает 2.
Почему оба выдают одинаковое значение?
И как понимать строку func(func($r))? Неужели функция может передавать саму себе в качестве аргумента?
Использование & в обявлении функции говорит о том, что переменная, переданная в нее будет изменена функцией. Таким образом func($r); добавляет 1 к переменной.
func(func($r)); можно разбить как бы на 2 этапа. func($r) и func(/*результат выполнения функции*/)
func($r) добавляет 1 к переменной $r и возвращает null (функции без return возвращают null). Таким образом, во вторую функцию уходит не $r, а null func(/*результат выполнения функции == null*/) , следовательно она уже никак не влияет на $r.
Чтобы использовать такие конструкции, нужно использовать return и соответственный стиль присваивания переменных:
<?php
function func($r) {
return $r+1;
}
$r = 1;
$r = func(func($r));
echo $r;
?>
func(func($r));
В этом случае вы должны получить предупреждение:
PHP Notice: Only variables should be passed by reference in ...
Первый (вложенный) вызов func() корректен, так как в него передаётся ссылка на переменную $r. При втором вызове никакой ссылки нет: роль аргумента выполняет значение, которое возвращает первый вызов func().
Выводы: читайте не только учебники, но и сообщения интерпретатора.
В дополнение к вышесказанному:
Если вы хотите пользоваться такой цепочечной передачей по ссылке, вам также нужно возвращать значение по ссылке:
function &func(&$r) {
$r++;
return $r;
}
$r = 1;
func(func($r));
echo $r; // 3
Обратите внимание на амперсанд перед именем функции.
Он говорит, что результат не нужно копировать во временное значение, нужно просто вернуть ссылку на ту же переменную.
Таким образом, происходит ровно то, что вы ожидаете. Функция изменяет внешнюю переменную и возвращает ссылку на неё, которую можно передать по в другую(или ту же) функцию, требующую ссылку на вход.
Код функции принимает аргумент по ссылке, то есть может менять его значение в вызывающем коде.
Почему оба выдают одинаковое значение?
Со вторым случаем все должно быть просто. Задали начальное значение переменной. Вызвали функцию, которая увеличила его значение. В результате имеем 2.
В первом же случае имеет место быть вложенный вызов функции. Здесь вызов func($r) аналогичным же образом увеличивает значение на 1. Далее результат выполнения функции (который собственно не определен, поскольку в функции нет инструкции return) передается как аргумент в эту же функцию еще раз. Но поскольку здесь аргументом вызова уже является не $r (а неопределенный результат первого вызова), то, конечно, значение этой переменной не изменится.
И как понимать строку func(func($r))
понимать ровно как написано, вызвать функцию func и ее результат еще раз передать в функцию func. То есть формально, если это вам проще воспринимать, это будет эквивалентно записи
$result = func($r);
func($result);
Неужели функция может передавать саму себе в качестве аргумента?
опять таки, передается результат выполнения, а не саму себя. Впрочем подход с передачей ссылки на функцию это весьма распространен. Это называется callback-методом (или функцией обратного вызова). Самый простой пример передачи функции в качестве параметра - сортировка usort(). Пример:
$data = [0,1,2,3, 1,2];
usort($data, function($a,$b){ return $a - $b;}) ;
//либо для PHP 7
usort($data, function($a, $b){ return $a <=> $b;});
Как видно здесь в качестве параметра передается ссылка на функцию. Причем функция эта анонимная, т.е. не имеет названия и определена прямо в месте передачи.
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники
Продвижение своими сайтами как стратегия роста и независимости