在php中引用取消设置变量

时间:2010-09-23 18:42:01

标签: php reference

我有一个包含对象数组的类,并且有通过引用从该数组返回对象的方法。还有一种方法可以从数组中取消设置对象。

但是,如果我有一个引用数组中对象的变量,并且该元素未设置,则该变量仍然具有对它的引用。我需要在remove方法中做些什么来彻底销毁该对象,包括对它的引用。

class myClass
{
    public $objectList = array();

    public function __construct()
    {
        $objectList[] = new myObject();
    }

    public function &getObjectByReference()
    {
         return $this->objectList[0];
    }

    public function removeObject()
    {
        unset($this->objectList[0]);
    }
}
$myClass = new myClass();
$referencedObject = $myClass->getObjectByReference(); 
// this can now use the methods from myObject
$myClass-> removeObject(); 
// supposed to delete the object from memory. However $referencedObject is still
// able to use all the methods from myObject.

这就是我遇到的问题,我需要能够从数组中删除并从内存中删除对象,以便引用该对象的变量不再可用。

4 个答案:

答案 0 :(得分:0)

你有没有尝试过:

$referencedObject = &$myClass->getObjectByReference();

在放入&?

后,$ referencedObject仍然存在

答案 1 :(得分:0)

要从返回值创建引用,函数必须通过引用返回(您已经这样做),并且赋值必须通过引用。所以你应该写:

$referencedObject =& $myClass->getObjectByReference();

如果你这样做,参考确实会被销毁。

但是如果你想要销毁所有具有此对象作为值的变量(以及引用)那么这是不可能的。您只能删除实际引用,而不能删除具有相同值的变量;)

答案 2 :(得分:0)

Php正在使用垃圾收集器:如果仍然存在对该对象的引用,则该对象不会被删除。

unset($this->objectList[0])

不删除对象而是$ this-> objectList中的值,该对象仍然存在,因为他被$ referencedObject引用。

一个解决方案:当你删除对象时,告诉他他正被删除,并且在那个对象中你有一个布尔“isDeleted”。然后,对于该对象的每个方法,检查isDeleted是否为true,在这种情况下,只执行任何操作。

答案 3 :(得分:0)

这是PHP垃圾收集器的本质。要确保调用者不维护对象的引用,您必须确保它们永远不会触及原始对象。这是一个想法:

class myClass
{
    public $objectList = array();

    public function __construct()
    {
        $objectList[] = new Wrapper(new myObject());
    }

    public function getObject()
    {
         return $this->objectList[0];
    }

    public function removeObject()
    {
        $this->objectList[0]->emptyWrapper();
        unset($this->objectList[0]);
    }
}



class Wrapper {

    private $object;

    public function __construct($object) {
        $this->object = $object;
    }

    public function __call($method, $args) {
        return call_user_func_array(array($this->object, $method), $args);
    }

    public function __get($attr) {
        return $this->object->$attr;
    }

    public function __set($attr, $value) {
        $this->object->$attr = $value;
    }

    public function emptyWrapper() {
        $this->object = null;
    }

}

您可以使用此包装器的想法,也可以使用强制间接和句柄。我可能更喜欢使用强制间接;否则,调用者仍然可以保持包装器对象的存活 - 尽管它相当便宜。

class myClass
{
    public $objectList = array();

    public function __construct()
    {
        $objectList[] = new myObject();
    }

    public function getObjectHandle() {
        return 0;
    }

    public function removeObject($h)
    {
        unset($this->objectList[$h]);
    }

    public function call($h, $method, $args) {
        call_user_func(array($this->objectList[$h], $method), $args);
    }

    public function get($h, $attr) {
        return $this->objectList[$h]->$attr;
    }

    public function set($h, $attr, $value) {
        $this->objectList[$h]->$attr = $value;
    }

}

$myClass = new myClass();
$objectHandle = $myClass->getObjectHandle();
// example method call
$myClass->call($objectHandle, 'some_method', array('arg1', 'arg2')); 
$myClass->removeObject($objectHandle);