gpt4 book ai didi

perl - DESTROY 以意外的顺序调用

转载 作者:行者123 更新时间:2023-12-04 08:52:57 27 4
gpt4 key购买 nike

我开始注意到 Scope::Guard 的一些奇怪之处。 .

  • 如果我取消定义 $guard变量作为 sub 中的最后一个语句,守卫的 sub 得到
    比我预期的要晚打电话。
  • 如果我不取消它,或者如果我做了什么
    (任何)在 undef $guard 之后,当引用结束时它会被调用
    范围如文档所示。我想知道为什么。

  • 代码也可以找到 here
    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
    并获得至少对我来说出乎意料的完全相同的结果。

    我期待 $mySubGuardmySub()应该先销毁
    $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()被摧毁
    在外部作用域的局部变量被销毁之后。

    为什么行为不同只是因为我取消了一个即将消失的变量
    无论如何超出范围?为什么做某事很重要
    然后?

    最佳答案

    看起来这是某种优化。如果您 undef一个变量,之后不要使用它,它会被放入某种队列以检查魔法或其他东西。但是,如果您之后执行任何操作,它就会立即执行 DESTROY。

    此外,可能存在一个错误,因为您是 undef - 说一个“返回上下文”,有一个正在检查某事的变量的副本。也许 Perl 保留了一个引用,稍后它会清理它并结束调用范围。

    您还会注意到 undef 之后的任何其他语句-ing 守卫会导致预期的行为。包括 PBP 推荐的以 return 结尾的所有字幕. Damian 的明确原因之一是它避免了意外的副作用。

    问题已解决:就像 undef 一样简单- 一个守卫,你可以直接运行它的处理程序。不要 undef 守卫作为 sub 的最后一个(隐式返回)语句。有理由明确 undef 守卫,例如您想立即运行它们的处理程序,以进行进一步处理。

    这是令人困惑和意外的,但绝对不应该出现在完成或标准化的代码中。

    关于perl - DESTROY 以意外的顺序调用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11427281/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com