11

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

php手册说 “unset()破坏了指定的变量”

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

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

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

4

5 回答 5

15

让我们考虑一下这个功能:

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被删除。

请参阅引用计数基础知识

于 2010-07-06T21:39:21.197 回答
9

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

于 2010-07-06T20:12:57.390 回答
4

未设置(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 :)

有帮助吗?

于 2010-07-06T20:27:18.720 回答
1

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

unset($some_static_var_or_property_holding_a_big_object);

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

$some_static_var_or_property_holding_a_big_object = null;

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

于 2014-02-27T14:22:37.643 回答
0

好吧,unset()它的作用是清除与变量名相关的内存。

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

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

于 2010-07-06T20:32:54.150 回答