Чому посилання рідко використовуються в PHP?


26

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

Натомість код завжди використовує повернене значення замість того, щоб передавати посилання на змінну методу, який потім змінює значення цієї змінної та просто повертає її.

Я читав, що при використанні посилань використовується менше пам'яті, так чому вони не використовуються в PHP?


19
Використання параметрів проходження посилання - це "програмування побічних ефектів" - використання функції для повернення єдиного значення значно чіткіше при читанні коду. Однак, досить багато основних функцій PHP використовують посилання.
половина

3
PHP передає об'єкти за посиланням за посиланням.

2
Сортування масивів є основним прикладом основних функцій PHP, які передаються за посиланням
Mark Baker

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. Трохи ледача відповідь на цю ...
yannis

Для завершення відповіді було б непогано зазначити, що всі об'єкти передаються за посиланням у 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якщо значення є об'єктом, але, на мою думку, воно не повинно.)

В основному, я знайду лише пропускний посилання, корисний для параметрів "out", тобто змінні, які я очікую, щоб повернутися з функції, а не переходити, a la preg_match's &$matches. Навіть для функцій, які чітко модифікують об'єкт, що передається, на кшталт sortабо array_pop, який відчуває себе трохи прискіпливим ... але це ми застрягли.


5

PHP - веб-орієнтована мова.
Веб-сторінки подаються швидко і мають бути легкими.
Звичайна програма PHP живе частку секунди і споживає кілька сотень кілобайт пам'яті.
Немає користі для таких оптимізацій.


1
Це. Не потрібні вказівники / посилання, оскільки він не змішується на такому низькому рівні, як C ++.
Kenneth Worden

8
Чому ця публікація отримує 5+ ??? Це робить а) не відповісти на питання б) невірно

1
Тож посилання повільні і займають занадто багато пам’яті?
Rocket Hazmat

1
@RocketHazmat Так, як не дивно, це правда.
янніс

3

Деякі причини на льоту:

  • PHP - це сценарій мови, і не спрямований на використання в якості основного вбудованого програмного забезпечення (в основному, пам'ять очищається в кінці сценарію),
  • Оскільки PHP5, параметр "пропуск по посиланню" є неявним для параметрів об'єкта (тому PHP використовує "по вашій спині" передачу посилання).

1
Дивіться: php.net/manual/en/language.oop5.references.php для своєї другої точки.
янніс

2

Я думаю, що це лише вибір розробників, нічого спільного з мовою. Багато PHP-коду (вбудований і не) використовують посилання. Погляньте на функції масиву в PHP, багато з яких використовують посилання. preg_matchвикористовує посилання.

Я думаю, що одна з причин, що розробники вирішили не використовувати посилання, це тому, що це може заплутати. Ви викликаєте функцію, і одна із змінних може (або не може) бути оновлена, оскільки вона була посиланням. Отже, при налагодженні може бути не зрозуміло, чому значення $xjsut магічно змінилося.


1

Принципова проблема вашого запитання полягає в тому, що ви припускаєте, що це також є звичайним для C ++. Це не так. Ми не любимо вихідні параметри і використовуємо їх якомога рідше - вони дійсно поширені лише в API-стилях С.


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.