Почему я должен использовать оператор ссылки (& amp;) в вызове функции?

Настроить

Я заимствую функцию из CMS с открытым исходным кодом, которую я часто использую для пользовательского проекта.

Его цель не важна для этого вопроса, но если вы хотите знать, что это простой статический кеш, предназначенный для сокращения запросов к базе данных. Я могу вызывать getObject 10 раз при загрузке одной страницы, и мне не нужно беспокоиться о попадании в базу данных 10 раз.

Код

Упрощенная версия функции выглядит следующим образом:

function &staticStorage($name, $default_value = NULL)
{
static $data = array();
if (isset($data[$name])
{
return $data[$name];
}
$data[$name] = $default_value;
return $data[$name];
}

Эта функция будет вызываться примерно так:

function getObject($object_id)
{
$object = &staticStorage('object_' . $object_id);
if ($object)
{
return $object;
}

// This query isn't accurate but that's ok it's not important to the question.
$object = databaseQuery('SELECT * FROM Objects WHERE id = @object_id',
array('@object_id => $object_id'));
return $object;
}

Идея в том, чтобы однажды я позвонил static_storage возвращенное значение будет обновлять статическое хранилище по мере его изменения.

Эта проблема

Мой интерес в линии $object = &staticStorage('object_' . $object_id); Обратите внимание на & перед функцией. staticStorage Функция уже возвращает ссылку, поэтому я изначально не включал оператор ссылки, предшествующий вызову функции. Однако без ссылки, предшествующей вызову функции, она не будет работать правильно.

Я понимаю, что указатели, если я возвращаю указатель php будет автоматически приводить переменную как указатель $a = &$b вызовет $a указать на значение $b,

Вопрос

Зачем? Если функция возвращает ссылку, почему я должен использовать оператор ссылки, чтобы предшествовать вызову функции?

7

Решение

Из документов PHP

Note: Unlike parameter passing, here you have to use & in both places - to indicate that you want to return by reference, not a copy, and to indicate that reference binding, rather than usual assignment, should be done for $myValue.

http://php.net/manual/en/language.references.return.php

В основном, это поможет интерпретатору php. Первое использование в определении функции — это возвращение ссылки, а второе — привязка по значению вместо значения к назначению.

Положив & в объявлении функции функция возвратит адрес памяти возвращаемого значения. При присвоении этого адреса памяти значение будет интерпретироваться как int, если явно не указано иное, поэтому второе & необходим для оператора присваивания.

РЕДАКТИРОВАТЬ: Как указано @ ringø ниже, он не возвращает адрес памяти, а скорее объект, который будет обрабатываться как копия (технически копирование при записи).

2

Другие решения

PHP документ объясняет, как использовать и почему функции, которые возвращают ссылки.

В вашем коде getObject() функция также нуждается в & (и вызов также) в противном случае ссылка теряется и данные, хотя и могут быть использованы, основаны на PHP копирование при записи (возвращенные данные и исходные данные указывают на одни и те же фактические данные, пока не произойдет изменение в одном из них => двух блоков данных, имеющих различный срок службы)

Это не сработает (синтаксическая ошибка)

$a = array(1, 2, 3);
return &$a;

это не работает, как задумано (ссылка не возвращена)

$a = array(1, 2, 3);
$ref = &$a;
return $ref;

и без добавления & к вызову функции, как вы сказали, ссылка также не возвращается.

К вопросу о Зачем… Там, кажется, нет последовательного ответа.

  • если один из & отсутствует PHP обрабатывает данные, как если бы они не были ссылкой (например, возвращая массив) без каких-либо предупреждений
  • Вот некоторая странность, связанная с функциями, возвращающими ссылки

PHP развивался годами, но все еще наследует некоторые из первоначальных неудачных вариантов дизайна. Это, кажется, один из них (этот синтаксис подвержен ошибкам, так как можно легко пропустить один &… и без предупреждения впереди …; Кроме того, почему бы не вернуть ссылку прямо, как return &$var;?). PHP добился определенного прогресса, но еще, следы плохого дизайна сохраняются.

Вы также можете быть заинтересованы в этой главе документа, указанного выше

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

Наконец, лучше не искать слишком много эквивалентов между указателями в C и ссылками на PHP (в этом отношении Perl ближе, чем PHP). PHP добавляет слой между фактическим указателем на данные и переменными, а ссылки указывают скорее на этот уровень, чем на фактические данные. Но ссылка не указатель. Если $a это массив и $b это ссылка на $a, используя либо $a или же $b Доступ к массиву эквивалентен. Здесь нет разыменовать синтаксис *$b например, как в C. $b следует рассматривать как псевдоним $a, Это также причина, по которой функция может возвращать только ссылку на переменную.

2