我有一个数组,我用作堆栈来存储树中的路径。每个元素都指向树中的一个节点,我想关闭最后一个元素,然后将该元素引用的对象设置为null。
基本上:
$node = array_pop($path);
*$node = null;
假设PHP有一个'*'运算符作为C-ish语言。现在我有一个丑陋的解决方案,从父节点开始,记住我带了哪个孩子,然后将其设置为null,如下所示:
if($goLeft) {
$parent->left = null;
} else {
$parent->right = null;
}
我说这很难看,因为包含路径的数组是由我的树类中的公共函数创建的。我想公开直接在树中路径上的节点上工作的能力,而不暴露在PHP中解决特性(功能?)的实现细节。 ATM我需要在返回值中包含一个布尔值(在本例中为$ goLeft),这样我就可以解决无法取消引用引用的问题。
这是我第二次遇到这个问题,所以如果有人知道我可以做类似于第一段代码的方法,请分享!
(编辑)
在尝试了许多&和数组的排列之后,事实证明基本问题是我错误解释了我遇到错误的原因。
我试过
$a = ($x > $y) ? &$foo[$bar] : $blah;
并且出现“语法错误,意外错误”和“&” ”。我解释这意味着问题是在$foo[$bar]
上使用& -operator。事实证明,罪魁祸首是? - 操作者,如
if($x > $y) {
$a = &$foo[$bar];
} else {
$a = null;
}
完美无缺。因此,我进行了一场疯狂的追逐,寻找一个不存在的问题的解决方法。只要我没有破坏&的链,PHP就会做我想要的,即对变量引用的对象(不是变量本身)进行操作。实施例
$a1 = new SomeClass;
$a2 = &$a1;
$a3 = &$a2;
$a4 = &$a3;
$a4 = 42; // This actually sets $a1 to 42
var_dump($a1); // Emits 42
让我搞砸的是,我认为对象无论如何都是通过引用传递的(这是错误的),所以我不认为&如果表达式解析为对象,则是必需的。我的意思是:
class A {
public $b;
}
class B {}
$a = new A;
$a->b = new B;
$c1 = $a->b;
$c2 = &$a->b;
$c1 = 42; // Merely assigns 42 to $c1
$c2 = 42; // Assigns 42 to $a->b
事实证明,http://www.php.net/manual/en/language.oop5.references.php解决了这个问题。希望我第一次看到它时沉没了!
答案 0 :(得分:7)
非常有趣的问题!我可能找到了一种解决方法:如果使用对象引用填充数组,使用&
运算符,则可以通过将该数组值设置为NULL
来销毁原始对象。您必须直接对数组进行操作,而不是使用array_pop
返回的变量。之后,您可以弹出数组以释放该位置(然后将包含NULL
值)。
这就是我的意思(基于Rocket的代码):
$a=(object)'a';
$b=array(&$a);
$b[0] = NULL;
// array still contains an element
array_pop($b);
// now array is empty
var_dump($a); // NULL
答案 1 :(得分:1)
我希望我能记住我在哪里读到这个,但PHP的工作原理是维护一个对给定对象的引用计数器。您有一些对象(例如Tree
)具有对某些节点的引用。使用array_pop
时,将返回对节点对象的引用(即创建其他引用),但原始引用仍然存在。当您unset
弹出的引用时,它会被销毁,但原始对象不会被销毁,因为Tree
仍然具有该引用。释放该对象内存的唯一方法是让Tree
个人破坏它(这似乎是你在第二个代码块中所做的)。
PHP似乎没有任何强制内存释放或垃圾回收的方法,所以除非你仔细处理你的引用,否则你就会陷入困境。
这是不可能的
P.S。我仍然对你想要做的事感到困惑。 Rocket的解释有帮助,但是什么是$path
,它与第二个块有什么关系呢?
答案 2 :(得分:0)
只是不要指定array_pop()
返回值。
php > $test = array(1, 2, 3);
php > $test2 = array(0 => &$test[0], 1 => &$test[1], 2 => &$test[2]);
php > array_pop($test2);
php > var_dump($test);
array(3) {
[0]=>
&int(1)
[1]=>
&int(2)
[2]=>
int(3)
}
php > var_dump($test2);
array(2) {
[0]=>
&int(1)
[1]=>
&int(2)
}
答案 3 :(得分:0)
$one = 1;
$two = 2;
$array = array(&$one, &$two);
// magic
end($array);
$array[key($array)] = NULL;
var_dump($two);
// NULL
php中的引用允许您更改对象。