可以在PHP中取消引用引用吗?
我使用一个数组作为堆栈来存储通过树的路径。每个元素都指向树中的一个节点,我想弹出最后一个元素,然后将该元素引用的对象设置为null 基本上:可以在PHP中取消引用引用吗?,php,Php,我使用一个数组作为堆栈来存储通过树的路径。每个元素都指向树中的一个节点,我想弹出最后一个元素,然后将该元素引用的对象设置为null 基本上: $node = array_pop($path); *$node = null; 假设PHP和C-ish语言一样有一个“*”操作符。现在,我有一个丑陋的解决方案,从父节点开始,记住我取了哪个子节点,然后将其设置为null,如中所示: if($goLeft) { $parent->left = null; } else { $pare
$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]
上使用了&-运算符。事实证明凶手是?-接线员
if($x > $y) {
$a = &$foo[$bar];
} else {
$a = null;
}
很好用。因此,我开始了一场白费力气的追逐,为一个根本不存在的问题寻找解决办法。只要我不打破&’的链条,PHP就会做我想做的事情,即对变量引用的对象(而不是变量本身)进行操作。范例
让我搞砸的是,我认为对象无论如何都是通过引用传递的(这是错误的),所以如果表达式解析为对象,我认为&是不必要的。我的意思是:
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
事实证明,这个确切的问题是在。但愿我第一次读到它的时候,它就沉下去了 只需不分配
数组\u 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)
}
我希望我能记得我在哪里读到这篇文章,但是PHP通过维护对给定对象的引用计数器来工作。您有一些对象(例如
树
)引用了一些节点。使用array\u pop
时,将返回对节点对象的引用(即创建一个附加引用),但原始引用仍然存在。当取消设置
弹出的引用时,该引用将被销毁,但原始对象不会被销毁,因为树
仍然具有该引用。释放该对象内存的唯一方法是让Tree
亲自销毁它(这似乎是您在第二个代码块中所做的)
PHP似乎没有任何强制内存释放或垃圾回收的方法,因此除非您小心地处理引用,否则您将陷入困境
这是不可能的
顺便说一句,我仍然对你想做什么感到困惑。Rocket的解释很有帮助,但是什么是
$path
,它与第二个块有什么关系?非常有趣的问题!我可能已经找到了一个解决方法:如果使用对象引用填充数组,使用&
操作符,可以通过将该数组值设置为NULL
来销毁原始对象。您必须直接对数组进行操作,而不是使用array\u pop
返回的变量。之后,可以弹出数组以释放该位置(该位置将包含一个NULL
值)
这就是我的意思(基于火箭的代码):
php中的引用允许您更改对象。我不确定,这是您想要的,但您可以使用
unset($parent->left)
而不是$parent->left=null代码>@PLB:我想你的意思是取消链接
,而不是取消链接
@Rocket当然,我知道。我很累。我不明白你想做什么。您希望(如果存在)*$node=null做什么?也许你可以展示你的树类来帮助我们理解对于那些不理解的人,$path
是一个引用数组(指向对象)。他想通过引用取消设置原始对象<代码>$a=(对象)'a'$b=阵列($a)$c=数组_pop($b);echo$a->scalar;//'一个“
(是的,该代码有效:)。他只想使用$c
将$a
设置为空。不完全是这样。他想要的是取消设置“原始”对象($test[2]
)。为什么array\u pop
的返回值很重要?您正在以任何方式修改$test2
。嗯。。。从描述中很难看出这一点。:)我认为我最初的问题过于具体。我使用堆栈,或者试图将某些内容设置为null,这实际上并不重要。我需要更好地解释我自己。假设我有一个变量,它包含对某物的引用——一个对象,另一个变量,它不重要。示例:a=&b
现在我想对$a
引用的对象执行一个操作,在本例中是$b
。也许我想将$b
设置为null,字符串“alice”,或者设置为另一个对象。没关系。不管怎么说,这就是我想要实现的。@kahulio这有点难以解释。基本上,$a=&$b
创建一个从$a
到$b
的符号表别名。也就是说,您对$a
所做的任何操作都会直接影响$b
。如果$b
是对象,则$a=$b
将对象引用从$b
复制到$a
。对对象$a
的操作与对对象$b
的操作具有相同的效果,但它是一个单独的符号表条目。如果您向$a
($a='blah';
)写入代码,它根本不会影响$b
<代码>数组\u 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)
}
$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
$one = 1;
$two = 2;
$array = array(&$one, &$two);
// magic
end($array);
$array[key($array)] = NULL;
var_dump($two);
// NULL