Я начал замечать что-то странное вScope::Guard
.
$guard
как самого последнего оператора в подпрограмме, подпрограмма охранника получает позвонили позже, чем я ожидал.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. Если я не использую строку undef $mySubGuard
в mySub, я получаю вывод ниже:
mySub returned a undefined value
shouldDestroyLast
shouldDestroyFirst
done
Итак, похоже, что $mySubGuard
из mySub()
уничтожен. после того, как переменные, локальные для внешней области, будут уничтожены.
Почему поведение отличается только потому, что я не определяю переменную, которая вот-вот перейдет? все-таки выходит за рамки? И какая разница, сделано ли что-то после?