【问题标题】:unset variable in php在php中取消设置变量
【发布时间】:2011-03-12 12:20:59
【问题描述】:

我刚刚通过 php 手册阅读了有关未设置变量的信息。

php 手册说 “unset() 销毁指定变量”

在我遇到静态变量之前,这个 def 似乎很完美... “如果静态变量在函数内部是 unset(),unset() 只会在函数其余部分的上下文中销毁该变量。随后的调用将恢复变量的先前值。”

这个定义对我来说似乎不是一个好定义,至少,因为“销毁变量”意味着该变量不再与该内存位置相关联。

还有其他人认为更好的定义是“unset() 使变量超出当前范围”吗?我的意思是,与其指向生命周期,不如在这里使用单词范围?

【问题讨论】:

  • 这对 SO 来说不是一个好问题。您可以在 PHP 邮件列表或其他内容中声明此类内容,但在这里没有任何价值。您希望从答案中得到什么?如果我说 Yes 你满意吗? ;)
  • felix,我只是一个初学者,如果你说是,那肯定会增强我的信心,如果你说不,那么肯定会学到一些东西,但从接下来我会照顾好这个。谢谢跨度>

标签: php static unset


【解决方案1】:

让我们考虑一下函数:

function foo() {
    static $bar;
    $bar++;
    unset($bar);
}
foo(); //static $bar is 1
foo(); //static $bar is 2

函数编译为:

函数名:foo 操作数:11 编译后的变量:!0 = $bar line # * op fetch ext 返回操作数 -------------------------------------------------- ------------------------------------------- 2 0 > EXT_NOP 4 1 EXT_STMT 2 FETCH_W 静态 $0 'bar' 3 ASSIGN_REF !0, $0 5 4 EXT_STMT 5 POST_INC ~1 !0 6 免费 ~1 6 7 EXT_STMT 8 UNSET_VAR !0 7 9 EXT_STMT 10 > 返回空

一个变量实际上存在于对foo() 的每个函数调用之外,并且在每次调用时,都会获取它并将对它的引用分配给$bar。其实和这个很像:

function foo() {
    global $bar;
    $bar++;
    unset($bar);
}

当您调用unset() 时,您只是在破坏您创建的引用,而不是基础值。

我没有确认,但我猜是这样的:

  • 存储变量的底层表示(zval),使其引用计数为 1。
  • 当调用foo() 时,符号$bar 与此zval 相关联,其引用计数增加到2 并设置引用标志。
  • 当调用unset 时,zval 的引用计数减为1,引用标志可能被清除,符号$bar 被删除。

reference count basics

【讨论】:

  • @artefactor 我很想知道你是如何产生这个输出的?
  • @Artefacto,这是 HHVM 还是 ZE 的输出?
【解决方案2】:

在函数内部,引用静态变量的变量名就是……引用。实际上, unset 会破坏引用。

【讨论】:

  • 你的意思是说我将一个静态变量声明为(考虑在 fn 中)static $a=2; $b=$a+2;//这里的$a成为静态变量$a的引用;?先生,我没明白你的意思
  • 对于静态变量,在堆上为数据值分配空间,在栈上为引用链接分配空间。取消设置引用时,只有本地堆栈空间被销毁/回收/无效。
【解决方案3】:

unset(self::$somethingstatic);将引发致命错误,因为变量是静态的(始终存在,无法取消设置)。

文档特别提到了函数内部定义的静态变量,请考虑:

function t($stage)
{
  static $shell = 23;
  switch($stage) {
    case 1:
      $shell++;
      break;
    case 2:
      unset($shell);
      break;
    case 3:
      $shell--;
    break;
  }
  echo $shell;
}

因为 $shell 是一个静态变量,它总是存在(静态),所以任何其他时候你提到 $shell 只是一个引用 - 当你取消它时,你正在取消引用(想想取消链接符号链接) -然而静态变量仍然存在(这就是静态的意思)。

因此,如果您调用上述函数 t(1) 将回显 24,t(2) 将不回显任何内容,而 t(3) 将(正确地)回显 23 :)

有什么帮助吗?

【讨论】:

  • 我喜欢说“任何其他时候你提到 $shell 这只是一个参考:”但是 AFAIK ..in php 内存甚至被分配用于参考??纠正我
  • thankz nathan i din,t know abt unsetting static property ll give error
【解决方案4】:

如果没有错,关键是取消设置静态变量。由于不同的原因,这可能很有用,此外这会释放一些内存。例如:

unset($some_static_var_or_property_holding_a_big_object);

虽然我们无法完全按原样做到这一点,但在某些情况下足以做到这一点:

$some_static_var_or_property_holding_a_big_object = null;

这会释放一些内存(我猜)并允许我们销毁我们不再想要的对象(我希望我没有跑题)。

【讨论】:

    【解决方案5】:

    好吧,unset() 所做的是清除与变量名相关的内存。

    然而,在静态变量的情况下,您可以想象正在发生的事情是将静态变量与函数的范围分开,并且每次调用函数时,您都会自动获得该变量的副本。

    所以,这意味着如果你 unset 一个静态变量,你实际上只是 unsetting 该副本,所以当再次调用该函数时,它会“接收”一个新副本。

    【讨论】:

    • 如果我只是想象 unset() 将变量踢出范围,那有什么问题,现在无论它是否清除与变量关联的内存,这取决于变量的生命周期。
    • 好吧,你所说的问题是,实际上,static 声明的变量不在函数的范围内,这就是它延续的原因从一个电话到另一个电话。 OTOH,如果您认为这是您“踢出范围”的静态变量的副本,那么您就走在了正确的轨道上
    猜你喜欢
    • 2017-11-14
    • 2016-10-01
    • 2013-02-17
    • 1970-01-01
    • 2020-05-28
    • 2014-11-07
    • 2011-02-06
    • 2012-08-30
    相关资源
    最近更新 更多