在PHP中,所有值都保存在所谓的zvals中.这些zvals包含实际的数据,类型信息,这对您的问题很重要 – 引用计数.看看下面的代码段:
$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)
一旦引用计数到达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,则两者的引用将为1,但它们仍将被释放(和__destructed).在这种情况下,尽管破坏的顺序是未定义的行为.