Я заимствую функцию из 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
,
Зачем? Если функция возвращает ссылку, почему я должен использовать оператор ссылки, чтобы предшествовать вызову функции?
Из документов 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ø ниже, он не возвращает адрес памяти, а скорее объект, который будет обрабатываться как копия (технически копирование при записи).
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
, Это также причина, по которой функция может возвращать только ссылку на переменную.