我不明白如何从函数返回一个对象。由于对象是通过引用传递和返回的,如果我在函数中创建了一个对象,我希望在函数完成执行后销毁这样的对象。所以这样的返回对象引用应该是指不存在的(被破坏的)对象。但是我在函数中创建的对象已成功返回。怎么来的?
class O{
public $ppty = "ppty value";
}
function f1(){
$o1 = new O();
return $o1;
}
var_dump(f1());
**Result:**
object(O)[15]
public 'ppty' => string 'ppty value' (length=10)
答案 0 :(得分:6)
变量"持有"对象实际上是持有对象的引用。该对象存在于内存中,引用该对象的变量只保存内存地址(过于简化)。 那是的参考。当返回该引用或将其传递到某个地方或将其分配给另一个变量时,将引用该引用的副本(意味着复制了内存地址值;例如,从您的返回值0xDEADBEAF
功能;再次,过度简化)。这些引用被视为对象的属性;只有当引用计数达到0(没有变量持有对象的引用)时,才会收集对象垃圾。
答案 1 :(得分:2)
考虑以下示例:
$var = 'test';
$ref = &$var;
unset($ref);
echo $var; // Echoes "test".
取消设置仅删除$var
到$ref
的引用,而不是销毁$ref
引用的原始变量。这类似于引用对象的示例,垃圾收集只删除变量对对象的引用,但该对象仍然存在于内存中。
有关详细信息,请参阅http://php.net/manual/en/language.references.unset.php。
答案 2 :(得分:1)
当应用程序的功能或范围完成时,将删除不再可访问的局部变量。但是,当您从类创建对象时,方案是不同的。它们不会被自动删除,php中有一个垃圾收集器,它不断搜索不再可访问的对象,如果发现它将删除它们。
因此,当您从函数返回对象引用时,它将不会被删除。如果您不想在任何变量中存储引用,GC将在以后删除它。
有关php中垃圾收集器的更多信息,请阅读以下链接:
答案 3 :(得分:0)
在PHP中,所有值都存储在zvals中。这些zval包含实际数据和类型信息。签出以下示例。
<?php
class O{
public $ppty = "ppty value";
}
$a = new 0; // $a is pointing to zval(class 0) with refcount 1
$b = $a; // $a and $b are pointing to zval(class 0) with refcount 2
$c = $b; // $a, $b and $c are pointing to zval(class 0) with refcount 3
unset($a) // new $b and $c are pointing to zval(class 0) with refcount 2
// until the refcount is greater then the 0 the destructor will not called
?>
现在看看下面的例子
<?php
$a = new 0; // $a is pointing to zval(class 0) with refcount 1
unset($a) // here refcount is 0 and destruct will be called
?>
现在来看你的例子
<?php
function f1(){
$o1 = new O(); // refcount = 1
return $o1;
}
// now you are returning the object in function f1 and so,
// $o1 is gone after the function scope but the func f1 is now pointing the its reference.
var_dump(f1())
**Result:**
object(O)[15]
public 'ppty' => string 'ppty value' (length=10)
//一旦完成该过程,它就会调用destruct。