我开始注意到一些奇怪的事情Scope::Guard
。
- 如果我将一个
$guard
变量取消定义为 sub 中的最后一条语句,则守卫的 sub 被调用的时间比我预期的要晚。 - 如果我不取消定义它,或者如果我在 之后做某事(任何事情)
undef $guard
,它会在引用超出记录的范围时被调用。我想知道为什么。
代码也可以在这里找到
my $sClass = 'SGuard';
# Uncomment to use Scope::Guard instead:
# use Scope::Guard; $sClass = 'Scope::Guard';
package SGuard;
sub new {
my ($class, $sub) = @_;
return bless { sub => $sub }, $class;
}
sub DESTROY {
my ($self) = @_;
$self->{sub}->();
}
package main;
sub mySub {
my $mySubGuard = $sClass->new(sub {
print "shouldDestroyFirst\n"
});
# Do something - any no-op will do.
undef;
# Comment out this line and it works
undef $mySubGuard;
# Or uncomment the next undef line and it works. Any statement(s) or
# no-ops will do but we test the return value of mySub to make sure it
# doesn't return a reference, so undef...
# undef;
}
{
my $scopeGuard = $sClass->new(sub {
print "shouldDestroyLast\n"
});
# Check that mySub returns undef to ensure the reference *did* go out
# of scope
printf "mySub returned a %sdefined value\n", defined mySub() ? "" : "un";
}
print "done\n";
在代码中,我制作了自己的穷人Scope::Guard
(SGuard
上面),只是为了使示例尽可能简单。您还可以使用Scope::Guard
并获得至少对我来说出乎意料的完全相同的结果。
我期望$mySubGuard
内部mySub()
应该首先被销毁$scopeGuard
,调用的范围内mySub()
应该最后被销毁。所以得到如下输出:
shouldDestroyFirst
mySub returned a undefined value
shouldDestroyLast
done
如果我undef $mySubGuard
在 mySub 中使用 line,我会得到以上输出。如果我不在undef $mySubGuard
mySub 中使用 line,我会得到以下输出:
mySub returned a undefined value
shouldDestroyLast
shouldDestroyFirst
done
因此,看起来在外部作用域的本地变量被销毁后, $mySubGuard
frommySub()
被销毁了。
为什么行为会因为我取消定义一个即将超出范围的变量而有所不同?为什么事后是否做某事很重要?