【问题标题】:Why do I have to use the reference operator (&) in a function call?为什么我必须在函数调用中使用引用运算符 (&)?
【发布时间】:2016-04-28 04:23:09
【问题描述】:

设置

我从一个开源 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 pointers pass-by-reference


    【解决方案1】:

    来自 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,这就是赋值运算符需要第二个 & 的原因。

    编辑:正如下面@ri​​ngø 所指出的,它不返回内存地址,而是一个将被视为副本的对象(技术上是写时复制)。

    【讨论】:

    • @ringø,我不确定最后一段,因为我只是在测试自己。当我 var_dump() 一个没有& 的变量时,我仍然得到一个对象。这让我相信它将在写入时复制而不是更改原始对象,但我尚未对此进行测试。
    【解决方案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 会将数据视为不是引用(例如返回数组),而不会发出任何警告
    • here 与返回引用的函数相关的一些奇怪现象

    PHP 多年来不断发展,但仍然继承了一些最初糟糕的设计选择。这似乎是其中之一(这种语法很容易出错,因为一个人可能很容易错过一个&...并且没有提前警告...;还有为什么不直接返回像return &$var; 这样的引用?)。 PHP 取得了一些进展,但 still,仍然存在设计不佳的痕迹。

    您可能也对上面链接的文档的这一章感兴趣

    不要使用 return-by-reference 来提高性能。引擎会自行自动优化。仅在您有正当的技术理由时才返回参考资料。

    最后,最好不要过多地寻找 C 中的指针和 PHP 引用之间的等价性(Perl 在这方面比 PHP 更接近)。 PHP 在指向数据的实际指针和变量之间添加了一个层,并且引用指向该层而不是实际数据。但是引用不是指针。如果$a 是一个数组并且$b 是对$a 的引用,则使用$a$b 访问该数组是等效的。没有 dereference 语法,例如 C 中的 *$b$b 应该被视为 $a 的别名。这也是函数只能返回对变量的引用的原因。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-07-02
      • 2022-01-17
      • 2017-01-16
      • 2023-04-03
      • 2020-08-09
      • 2011-03-07
      • 2016-10-17
      相关资源
      最近更新 更多