【发布时间】:2015-06-24 08:40:35
【问题描述】:
如何在perl中创建对对象的弱引用,这样当对象超出范围时,引用计数就会被释放?
我尝试使用 DESTROY 子来打破循环引用。
sub DESTROY{
my $p = shift;
delete $p->{__tree__};
delete $p->{tokenizers};
delete $p->{toke};
}
请帮忙。
【问题讨论】:
如何在perl中创建对对象的弱引用,这样当对象超出范围时,引用计数就会被释放?
我尝试使用 DESTROY 子来打破循环引用。
sub DESTROY{
my $p = shift;
delete $p->{__tree__};
delete $p->{tokenizers};
delete $p->{toke};
}
请帮忙。
【问题讨论】:
您不能“调用”destroy - 这里的问题是 perl 对引用计数起作用 - 对事物的每个引用都会被计数,并且 仅 当引用计数降至零时,它可以被释放/销毁/垃圾收集。
DESTROY 是一个特殊的方法,它在对象内调用以执行清理任务当这种情况发生时。它不会删除对象,它只是让它在它死后做一些最后的整理。
看看Scalar::Util 模块。它包括 weaken 方法,该方法完全符合您的要求。
左值 $ref 将变成弱引用。这意味着它不会对它引用的对象进行引用计数。此外,当该对象的引用计数达到零时,该引用将设置为 undef。此函数改变作为其参数传递的左值并且不返回任何值。
这对于保留引用的副本很有用,但您不想阻止对象在通常的时间被销毁。
【讨论】:
来自perldoc:
您可以通过创建“弱引用”来破坏循环引用。弱引用不会增加变量的引用计数,这意味着对象可能会超出范围并被销毁。您可以使用 Scalar::Util 模块导出的弱化函数来弱化引用。
以下是我们如何使第一个示例更安全的方法:
use Scalar::Util 'weaken';
my $foo = {};
my $bar = { foo => $foo };
$foo->{bar} = $bar;
weaken $foo->{bar};
从
$foo到$bar的引用已被削弱。当$bar变量超出范围时,它将被垃圾回收。下次查看$foo->{bar} key的值时,将是undef。这个远距离的动作可能会让人困惑,所以你应该小心使用弱化。您应该在将超出范围的变量中削弱引用first。这样,寿命更长的变量将包含预期的引用,直到它超出范围。
【讨论】: