假设我们有类 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
,但它们仍将被释放(和 __destruct
ed)。在这种情况下,尽管销毁顺序是未定义的行为。
关于php - 什么决定了类对象在 PHP 中何时被销毁?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8523433/