在Perl中,为什么复制弱引用会创建一个正常的,强大的引用?

key*_*ey_ 10 perl weak-references

Scalar :: Util :: weaken说:

注意:复制弱引用会创建一个正常的强引用.

我无法理解为什么Perl会这样处理它.在我的应用程序中,我 weaken用来打破周期.有时我必须削弱那些已经很弱的引用,如果Perl不这样做的话.

Eri*_*rom 13

每次将引用复制到新变量时,引用计数都会递增.复制弱引用或强引用时都是如此.

my $obj = {};    # 1 reference to {} stored in $obj

my $copy = $obj; # 2 references

weaken $obj;     # 1 reference
Run Code Online (Sandbox Code Playgroud)

此时,如果$copy超出范围,引用计数将降为零,并释放内存.现在假设以下代码:

my $newref = $obj;  # 2 references

undef $copy;        # 1 reference
Run Code Online (Sandbox Code Playgroud)

如果Perl保留了弱引用$newref,那么当$copy清除时,哈希会被意外地处理掉.这会打破这样的期望,即当您复制引用时,它至少会与副本一起保留.

简而言之,如果在赋值中持续存在弱引用,则会强制您使用无数弱点检查来丢弃代码,并且需要一些其他方法来取消变量,以避免不可避免的变量自杀问题.


Ven*_*tsu 10

我认为这是一个封装问题.如果第三方库在内部使用弱引用,我的代码不应该提前知道当我复制一个引用它可能会突然消失在我身上时.Perl通常的期望是,只要存在,ref就会保持有效.当你打电话给weaken你时,基本上已经答应你将采取所需的步骤,在你使用它之前检查引用是否仍然有效.

作为第二个原因,削弱弱参考的强大副本的界面相当紧张.

my $new_ref = $old_ref; if (isweak($old_ref)) { weaken($new_ref); }
Run Code Online (Sandbox Code Playgroud)

如果弱引用创建弱引用,则执行相同操作以获得强引用的代码稍微复杂一些.

my $new_ref;
if (ref($old_ref) eq 'ARRAY') {
    $new_ref = \@{$old_ref};
}
elsif (ref($old_ref) eq 'HASH') {
    $new_ref = \%{$old_ref};
}
elsif (.....
Run Code Online (Sandbox Code Playgroud)

如果您知道ref只能是一种类型,您可以保存if/ elsifcascade并简单地执行deref-reref,但是仍然更难判断为什么要取消引用以获取新引用.下一个维护者将尝试"修复"您的代码.