php - 什么决定了类对象在 PHP 中何时被销毁?

标签 php class destructor instantiation

假设我们有类 CFoo。在以下示例中,何时调用 CFoo::__destruct()

function MyPHPFunc()
{
  $foo = new CFoo();

  . . .

  // When/where/how does $foo get destroyed/deleted?
}

在这个例子中,当脚本退出 MyPHPFunc 的范围时是否会调用析构函数,因为 $foo 将不再可访问?

最佳答案

在 PHP 中,所有值都保存在所谓的 zval 中。那些 zval 包含实际数据、类型信息和(这对您的问题很重要)引用计数。看看下面的片段:

$a = new B; // $a         points to zval(new B) with refcount=1
$b = $a;    // $a, $b     point to  zval(new B) with refcount=2 (+1)
$c = $b;    // $a, $b, $c point to  zval(new B) with refcount=3 (+1)
unset($a);  //     $b, $c point to  zval(new B) with refcount=2 (-1)

一旦 refcount 达到 0,就会释放 zval 并调用对象析构函数。

以下是 refcount 达到 0 的一些示例:

  • 取消设置一个变量:

    $a = new B; // refcount=1
    unset($a);  // refcount=0 => __destruct!
    

    但是:

    $a = new B; // refcount=1
    $b = $a;    // refcount=2
    unset($a);  // refcount=1 => no destruct as refcount > 0, even though unset() was called!
    
  • 离开函数(或方法)作用域

    function a() {
        $a = new B; // refcount=1
    }               // refcount=0 => __destruct! (as $a does not exist anymore)
    
  • 脚本执行结束

    $a = new B; // refcount=1
    die();      // refcount=0 => __destruct! (on script execution end all vars are freed)
    // doesn't need to be die(), can be just normal execution end
    

这些显然不是导致 refcount 减少的所有条件,而是您最常遇到的条件。

我还应该提到,因为 PHP 5.3 循环引用也会被检测到。因此,如果对象 $a 引用对象 $b 并且 $b 引用 $a 并且没有任何进一步的对 $a$b 的引用,两者的 refcount 都将为 1,但它们仍将被释放(和 __destructed)。在这种情况下,尽管销毁顺序是未定义的行为。

关于php - 什么决定了类对象在 PHP 中何时被销毁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8523433/

相关文章:

javascript - 比较 onkeyup javascript 时仅使用第一个数字

javascript - 将 dojo.declare 更改为 "native Javascript class decleration"

c++ - 我如何调用一个函数,它在一个单独的类中打印出一组结构?

c++ - 当对象在堆栈上声明时,你能保证析构函数的顺序吗?

c++ - 具有指针数组 C++ 的类的析构函数

Php Excel 设置整列数据对齐不起作用

javascript - 如何将一个类添加到 html 中提交类型的输入中,这样它一旦添加就不会被删除?

php - 使用连接表进行 codeigniter 搜索

c++ - Arduino:Setup() 不会启动

c++ - 析构函数如何在派生类中工作。 C++