Почему ссылки редко используются в PHP?


26

У меня есть некоторые знания C ++, и я знаю, что там часто используются указатели, но я начал изучать открытый исходный код PHP и никогда не вижу кода, использующего ссылки в методах.

Вместо этого код всегда использует возвращаемое значение вместо передачи ссылки на переменную в метод, который затем изменяет значение этой переменной и просто возвращает его.

Я читал, что использование ссылок использует меньше памяти, так почему они не используются в PHP?


19
Использование параметров передачи по ссылке - это «программирование побочных эффектов» - использование функции для возврата одного значения значительно понятнее при чтении кода. Тем не менее, довольно много основных функций PHP используют ссылки.
Галафер

3
PHP передает объекты по ссылке по умолчанию.

2
сортировки массивов - это основной пример основных функций PHP, которые передаются по ссылке
Марк Бейкер

2
Ссылки на PHP не являются указателями, и часто являются проблемой в заднице, если вы не ожидаете их там, где они появляются.
Lanzz

2
Если вам нужно несколько возвратов, return array($foo, $bar);иlist($A, $B) = foobar();
Изката

Ответы:


49

Ваше утверждение, что ссылки используются редко, неверно. Как уже упоминалось, есть множество нативных функций, которые используют ссылки, известные примеры включают функции сортировки массивов и preg_match()/ preg_match_all(). Если вы используете любую из этих функций в своем коде, вы также используете ссылки.

В дальнейшем ссылки в PHP не являются указателями. Так как вы пришли из C ++, я могу понять путаницу, но ссылки на PHP - это совершенно другой зверь, они являются псевдонимами таблицы символов . Любой прирост производительности, который вы могли ожидать от ссылок C ++, просто не применим к ссылкам PHP.

Фактически, в большинстве сценариев передача по значению происходит быстрее и требует меньше памяти, чем передача по ссылке. Zend Engine, ядро ​​PHP, использует механизм оптимизации копирования при записи , который не создает копию переменной, пока она не будет изменена. Передача по ссылке обычно нарушает шаблон копирования при записи и требует копию независимо от того, изменили вы значение или нет.

Не бойтесь использовать ссылки в PHP, когда это необходимо, но не делайте это как попытку микрооптимизации. Помните, преждевременная оптимизация - корень всего зла .

Дальнейшее чтение:


Спасибо за исправление @NikiC. Немного ленивый ответ на этот ...
Яннис

Чтобы завершить ответ, было бы неплохо отметить, что все объекты передаются по ссылке в PHP.
Флориан Маргейн

@FlorianMargaine Это не совсем точно (см. Вторую ссылку в дальнейшем чтении).
Яннис

2
@FlorianMargaine Нет, они очень разные, и важно понять, почему это так.
phant0m

3
@FlorianMargaine Нет, предположим, что объекты были переданы по ссылке в PHP: f($obj)дано function f($x) { $x = new X; }, будет иметь ссылку $objна другой объект, чем до вызова f(). Однако, поскольку объекты не передаются по ссылке, $ obj не изменяется, если вы выполняете это с помощью PHP. Таким образом, PHP делает то же самое, что и Java.
phant0m

8

PHP уже выполняет функцию копирования при записи, где он не создает новое значение, пока вы что-то не измените, поэтому при использовании ссылок не так много памяти сохраняется. Это может даже испортить некоторые вещи, которые PHP делает внутренне, чтобы уменьшить использование памяти, что делает вещи еще хуже.

Добавьте к этому тот факт, что ссылки делают вещи слишком волшебными в целом. По умолчанию и, следовательно, то, что большинство людей ожидают, это передача по значению; когда я перехожу $iк функции, это очень усложняет задачу: нужно ли заботиться о том, таинственно ли эта функция меняется $iна что-то другое, и, таким образом, делать защитные копии на всякий случай. (Он уже может измениться, $iесли значение является объектом, но, по моему мнению, не должен.)

В принципе, я бы только найти проход по ссылке полезной для «из» параметров, то есть переменный я ожидать , чтобы вернуться из функции , а не переходит в, а - ля preg_match«ы &$matches. Даже для функций, которые явно изменяют передаваемый объект, вроде sortили array_pop, это кажется немного странным ... но это то, с чем мы застряли.


5

PHP - это веб-ориентированный язык.
Веб-страницы обслуживаются быстро и должны быть легкими.
Обычная PHP-программа живет доли секунды и потребляет несколько сотен килобайт памяти.
Там нет смысла для такой оптимизации.


1
Это. Не нуждается в указателях / ссылках, так как он не портится на таком низком уровне, как C ++.
Кеннет Уорден

8
Почему этот пост получает 5+ ??? А) не отвечает на вопрос б) не правильно

1
Значит ссылки медленные и занимают слишком много памяти?
Ракета Хазмат

1
@ RocketHazmat Да, как ни странно, это правда.
Яннис

3

Несколько причин на лету:

  • PHP является языком сценариев и не предназначен для использования в качестве основного встроенного программного обеспечения (в основном, память очищается в конце сценария),
  • Начиная с PHP5, передача по ссылке неявна для параметров объекта (поэтому PHP использует передачу по ссылке «в вашу спину»).

1
См. Php.net/manual/en/language.oop5.references.php для вашего второго пункта.
Яннис

2

Я думаю, что это просто выбор разработчиков, ничего общего с языком. Много PHP-кода (встроенного и не) использовать ссылки. Посмотрите на функции массива в PHP, многие из них используют ссылки. preg_matchиспользует ссылки.

Я думаю, что одна из причин, по которой разработчики решили не использовать ссылки, заключается в том, что это может сбить с толку. Вы вызываете функцию, и одна из переменных может (или не может) обновляться, потому что это была ссылка. Таким образом, при отладке может быть непонятно, почему значение $xjsut волшебным образом изменилось.


1

Основная проблема в вашем вопросе состоит в том, что вы предполагаете, что это распространено и в C ++. Это не так. Нам не нравятся выходные параметры, и мы используем их как можно меньше - они действительно распространены только в API в стиле C.


0

Я знаю много функций PHP, которые делают это. Посмотрите, preg_match()например. $matchesбудет передано по ссылке

Если вы хотите написать для себя функцию, которая принимает аргументы по ссылке, используйте следующий синтаксис

function byref(&$a, &$b, $c) {
    $a += $c;
    $b += $c;
    return $a * $b;
}

$ a и $ b передаются по ссылке. $ c передается по значению.

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.