我从一个我经常用于自定义项目的开源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
的值。
为什么呢?如果函数返回一个引用,为什么我必须在函数调用之前使用引用运算符?
答案 0 :(得分:2)
来自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ø所指出的那样,它不会返回一个内存地址,而是一个将被视为副本的对象(技术上是写时复制)。
答案 1 :(得分:2)
PHP doc解释了如何使用以及为什么返回引用的函数。
在您的代码中,getObject()
函数还需要&
(以及调用),否则引用将丢失,数据虽然可用,但基于PHP copy-on-write(返回的数据和源数据都指向相同的实际数据,直到其中一个数据发生变化=>两个具有不同生命的数据块)
这不会起作用(语法错误)
$a = array(1, 2, 3);
return &$a;
这并没有按预期工作(没有返回参考)
$a = array(1, 2, 3);
$ref = &$a;
return $ref;
并且没有像你所说的那样将&
添加到函数调用中,也没有返回引用。
关于为什么的问题......似乎并不是一致的答案。
&
中的一个,那么PHP将数据视为不是引用(例如返回数组),而不会发出任何警告 PHP在这些年中不断发展,但仍然继承了一些最初的糟糕设计选择。这似乎是其中之一(这种语法容易出错,因为人们可能很容易错过一个&
...而且前面没有警告......;为什么不直接返回像return &$var;
这样的引用?) 。 PHP取得了一些进展,但still,设计不良的痕迹存在。
您可能也对上面链接的文档的这一章感兴趣
不要使用按引用返回来提高性能。引擎将自动对其进行自动优化。只有在有正当技术理由的情况下才能返回引用。
最后,最好不要过多地考虑C和PHP引用中指针之间的等价性(Perl在这方面比PHP更接近)。 PHP在实际指向数据和变量的指针之间添加了一个层,而引用指向的是该层而不是实际数据。但引用是而不是指针。如果$a
是一个数组且$b
是$a
的引用,则使用$a
或$b
访问数组是等效的。没有取消引用语法,例如在*$b
中的$b
应该被视为$a
的别名。这也是函数只能返回对变量的引用的原因。