为什么我必须在函数调用中使用引用运算符 (&)?
Why do I have to use the reference operator (&) in a function call?
设置
我正在从我经常用于自定义项目的开源 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
,returned 值将在更改时更新静态存储。
问题
我感兴趣的是行 $object = &staticStorage('object_' . $object_id);
注意函数前面的 &
。 staticStorage
函数 return 已经是一个引用,所以我最初没有在函数调用之前包含引用运算符。但是,如果函数调用之前没有引用,它就无法正常工作。
我对指针的理解是如果我 return 一个指针 php 会自动将变量转换为指针 $a = &$b
会导致 $a
指向的值$b
.
问题
为什么?如果函数 return 是引用,为什么我必须在函数调用之前使用引用运算符?
来自 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 解释器。函数定义中第一个使用是return引用,第二个是通过引用而不是值绑定到赋值。
通过将 &
放在函数声明中,函数将 return 一个 return 值的内存地址。除非另有明确说明,否则在获取此内存地址时,赋值会将值解释为 int,这就是赋值运算符需要第二个 &
的原因。
编辑:正如下面@ringø所指出的,它不是return内存地址,而是一个将被视为副本的对象(技术上copy-on-write).
PHP doc 解释了 return 引用的函数的使用方法和原因。
在您的代码中,getObject()
函数还需要一个 &
(以及调用),否则引用将丢失,数据虽然可用,但基于 PHP copy-on-write(returned 数据和源数据都指向相同的实际数据,直到其中一个发生变化 => 两个数据块具有不同的生命周期)
这行不通(语法错误)
$a = array(1, 2, 3);
return &$a;
这没有按预期工作(没有参考 returned)
$a = array(1, 2, 3);
$ref = &$a;
return $ref;
并且没有像您所说的那样将 &
添加到函数调用中,也没有引用 returned。
关于为什么的问题...似乎没有一致的答案。
- 如果缺少
&
之一 PHP 将数据视为不是引用(例如 returning 数组),没有任何警告
- here 一些与函数相关的奇怪之处 returning 引用
PHP 经过多年的发展,但仍然继承了一些最初糟糕的设计选择。这似乎是其中之一(这种语法很容易出错,因为人们可能很容易错过一个 &
... 并且没有提前警告...;另外为什么不直接 return 像 [=17 这样的参考=]?)。 PHP 取得了一些进展,但 still,设计不佳的痕迹依然存在。
您可能也对上面链接的文档的这一章感兴趣
Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so.
最后,最好不要过多地寻找 C 中的指针和 PHP 引用之间的等价性(Perl 在这方面比 PHP 更接近)。 PHP 在指向数据的实际指针与变量和引用之间添加一层,而不是指向该层而不是实际数据。但是引用不是指针。如果 $a
是一个数组并且 $b
是对 $a
的引用,则使用 $a
或 $b
访问数组是等效的。没有 dereference 语法,例如 C 中的 *$b
。$b
应该被视为 $a
的别名。这也是函数只能 return 引用变量的原因。
设置
我正在从我经常用于自定义项目的开源 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
,returned 值将在更改时更新静态存储。
问题
我感兴趣的是行 $object = &staticStorage('object_' . $object_id);
注意函数前面的 &
。 staticStorage
函数 return 已经是一个引用,所以我最初没有在函数调用之前包含引用运算符。但是,如果函数调用之前没有引用,它就无法正常工作。
我对指针的理解是如果我 return 一个指针 php 会自动将变量转换为指针 $a = &$b
会导致 $a
指向的值$b
.
问题
为什么?如果函数 return 是引用,为什么我必须在函数调用之前使用引用运算符?
来自 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 解释器。函数定义中第一个使用是return引用,第二个是通过引用而不是值绑定到赋值。
通过将 &
放在函数声明中,函数将 return 一个 return 值的内存地址。除非另有明确说明,否则在获取此内存地址时,赋值会将值解释为 int,这就是赋值运算符需要第二个 &
的原因。
编辑:正如下面@ringø所指出的,它不是return内存地址,而是一个将被视为副本的对象(技术上copy-on-write).
PHP doc 解释了 return 引用的函数的使用方法和原因。
在您的代码中,getObject()
函数还需要一个 &
(以及调用),否则引用将丢失,数据虽然可用,但基于 PHP copy-on-write(returned 数据和源数据都指向相同的实际数据,直到其中一个发生变化 => 两个数据块具有不同的生命周期)
这行不通(语法错误)
$a = array(1, 2, 3);
return &$a;
这没有按预期工作(没有参考 returned)
$a = array(1, 2, 3);
$ref = &$a;
return $ref;
并且没有像您所说的那样将 &
添加到函数调用中,也没有引用 returned。
关于为什么的问题...似乎没有一致的答案。
- 如果缺少
&
之一 PHP 将数据视为不是引用(例如 returning 数组),没有任何警告 - here 一些与函数相关的奇怪之处 returning 引用
PHP 经过多年的发展,但仍然继承了一些最初糟糕的设计选择。这似乎是其中之一(这种语法很容易出错,因为人们可能很容易错过一个 &
... 并且没有提前警告...;另外为什么不直接 return 像 [=17 这样的参考=]?)。 PHP 取得了一些进展,但 still,设计不佳的痕迹依然存在。
您可能也对上面链接的文档的这一章感兴趣
Do not use return-by-reference to increase performance. The engine will automatically optimize this on its own. Only return references when you have a valid technical reason to do so.
最后,最好不要过多地寻找 C 中的指针和 PHP 引用之间的等价性(Perl 在这方面比 PHP 更接近)。 PHP 在指向数据的实际指针与变量和引用之间添加一层,而不是指向该层而不是实际数据。但是引用不是指针。如果 $a
是一个数组并且 $b
是对 $a
的引用,则使用 $a
或 $b
访问数组是等效的。没有 dereference 语法,例如 C 中的 *$b
。$b
应该被视为 $a
的别名。这也是函数只能 return 引用变量的原因。