【问题标题】:PHP variables: references or copiesPHP 变量:引用或副本
【发布时间】:2011-12-03 05:45:09
【问题描述】:

我对 PHP 变量引用的工作方式感到困惑。在下面的示例中,我希望能够以$bar[0]$barstack[0][0] 访问字符串hello。在第 1 步中通过引用传递数组似乎就足够了。

第二个例子不起作用。 $foostack[0]0] 是字符串 hello,但 $foo[0] 不存在。在某些时候,$foostack 的第一个元素会变成 $foo 的副本,而不是引用。

问题出在第 2 步的第一行:当我推送引用时,我希望弹出引用。但是array_pop 会返回一个副本。

其他人告诉我,如果我不得不担心引用和副本,那么 PHP 不是适合我的语言。这可能是我能得到的最佳答案。

FWIW,为了使var_dump 有用,它需要显示一些区分引用和副本的属性。它不是。也许还有其他功能?

我的第一个 PHP 项目似乎进展不顺利。有人可以帮助阐明 这段代码有问题吗?

<?php
echo "// This works!\n<br />" ;

// step 1
$bar = array() ;
$barstack = array( &$bar ) ;

// step 2
array_push( $barstack[0], 'hello' ) ;

// results
echo count( $barstack[0] ) .';' .count( $bar ) ;


echo "\n<br />// This doesn't :(\n<br />" ;

// step 1
$foo = array() ;
$foostack = array( &$foo ) ;

// step 2
$last = array_pop( $foostack ) ;
array_push( $last, 'hello' ) ;
array_push( $foostack, &$last ) ;

// results
echo count( $foostack[0] ) .';' .count( $foo ) ;


echo "\n<br />// Version:\n<br />" ;
echo phpversion() ."\n" ;
?>

结果可以在以下网址查看:

http://www.gostorageone.com/tqis/hi.php

版本是 4.3.10。升级服务器是不切实际的。

期望的结果:

  1. 如果我忽略了显而易见的事情,请解释一下
  2. 这是一个错误吗?有什么解决方法吗?

谢谢!

-吉姆

【问题讨论】:

  • 发帖前请自行检查。你可以使用 var_dump( $array ),它会告诉你数组中有什么。那么一切就都清楚了。
  • 对我来说这个问题似乎不符合 StackOverflow 的规则
  • @Sunny Jim - 为了获得更好的答复,请尝试在您的问题中添加您期望发生的事情和实际发生的事情。您的链接涵盖了其中一半,但另一半没有。
  • @Sunny Jim:刚刚看到你更新了你的问题。 var_dump 显示引用,它在值前面用&amp; 表示。我添加了一个答案,逐步解释会发生什么,我认为您只是错过了 array_pop 始终返回一个值,而不是参考/别名。我还在下面添加了一个工作示例。

标签: php return-by-reference


【解决方案1】:

您的代码工作正常,没有错误,并且独立于 PHP 4 或 5。如果简单地向您解释一下,也许会有所帮助。

让我们看一下在你看来不起作用的例子,看看实际发生了什么:

// step 1
$foo = array(); # 1.
$foostack = array( &$foo ); # 2.
  • 1.:您将变量$foo 初始化为一个空数组。
  • 2.:您将变量$foostack 初始化为一个数组,并且该数组的第一个元素是变量$foo 的别名。这和写的完全一样:$foostack[] =&amp; $foo;

进入下一步:

// step 2
$last = array_pop($foostack); # 3.
array_push($last, 'hello'); # 4.
array_push($foostack, &$last); # 5.
  • 3.:您将数组$foostack 的最后一个元素的 分配给$last,然后从数组$foostack 中删除最后一个元素。 注意: array_pop 返回一个值,而不是引用。
  • 4.:您将'hello' 作为新元素添加到$last 中的空数组中。
  • 5.:您将&amp;$last 作为新元素添加到$foostack

那么我们现在有哪些变量?

  • 首先$foo 只包含一个空数组。 $foostack 的最后一个元素曾经引用过它 (2.),但您在 (3.) 之后直接删除了它。由于$foo,它的值没有再改变,它只是一个空数组array()
  • 然后是$last,它在3..中得到了一个空数组。那只是一个空数组,它是一个值而不是引用。在 (4.) 中,您将字符串 'hello' 作为第一个元素添加到其中。 $last 是一个包含一个字符串元素的数组。
  • 然后是$foostack。这是一个数组,它在 (2.) 中获取对 $foo 的引用,然后在 (3.) 中删除该引用。最后添加了$last 的别名。

这正是您的其余代码输出的内容:

echo count($foostack[0]) .';'. count($foo);

$foostack[0]$last 的别名 - 以字符串 'hello' 作为唯一元素的数组,而 $foo 只是 $foo,空数组 array()

如果你用 PHP 4 或 5 执行它没有区别。


当您写的是“错误”时,我假设您只是无法实现您想要的。您可能正在寻找一个能够在删除数组之前返回对数组最后一个元素的引用的函数。让我们调用这个函数array_pop_ref()

// step 1
$foo = array();
$foostack = array( &$foo );

// step 2
$last =& array_pop_ref($foostack);
array_push($last, 'hello');
array_push($foostack, &$last);

// results
echo count($foostack[0]) .';' .count($foo); # 1;1

array_pop_ref 函数:

function &array_pop_ref(&$array)
{
    $result = NULL;
    if (!is_array($array)) return $result;
    $keys = array_keys($array);
    $end = end($keys);
    if (false === $end) return $result;
    $result =& $array[$end];
    array_pop($array);
    return $result;
}

【讨论】:

  • 谢谢。这至少是一个小时的咨询!可能让我免了几天的磕磕绊绊。
  • PHP 手册也有一些关于该主题的更多信息(事实上相当多),我认为将引用视为变量别名是个好主意。见这里:References Explained.
猜你喜欢
  • 1970-01-01
  • 2020-06-19
  • 2011-04-23
  • 2016-05-08
  • 1970-01-01
  • 2018-11-27
  • 2012-03-31
  • 2015-04-01
  • 1970-01-01
相关资源
最近更新 更多