Eval返回值

时间:2011-08-29 22:23:18

标签: perl eval return-value

代码是否正确?

my $ttt = eval {
 my @a=(1,2);
 return \@a;
};

print @$ttt[1]. "\n";

我想,eval块是在飞行中评估的,并且在执行后不存在。该决定是否存在任何缺陷?

3 个答案:

答案 0 :(得分:3)

eval块使用其余代码进行解析,其返回值是对数组@a的引用。该引用已分配给$ttt。当eval块超出范围时,@a仍然具有非零引用计数(感谢$ttt),因此它仍然存在。

答案 1 :(得分:3)

eval块仍然是内存中代码的一部分。这是你想避免的吗?如果是这样,这不是正确的方法,你应该解释更多你想要解决的根本问题。

代码将运行,但您在打印中使用了一个数组切片,您可能打算使用简单的数组取消引用:

print $$ttt[1]. "\n";

你也没有检查eval是否成功;以下进入打印然后(如果您启用了警告)给出了使用未初始化的值警告:

my $ttt = eval {
    die "horribly";
    my @a=(1,2);
    return \@a;
};

print @$ttt[1]. "\n";

答案 2 :(得分:3)

你使用eval是没用的,你没有检查结果,但我有一种感觉,你想要抓住的东西与eval无关,但是当变量是释放。

Perl使用引用计数来知道何时释放变量是安全的。一旦没有引用变量就会释放变量。除了引用之外,词法(my)变量也由它们的创建范围引用,包变量也由它们所在的包引用。

在“正常”情况下,变量将在范围退出时被销毁,因为它的唯一引用被删除*。范围由许多内容创建,包括subs和eval的curlies。这是一个例子:

use feature qw( say );

{ package D; DESTROY { say "Destroyed $_[0]"; } }

{
    my $x = bless({}, 'D');   # $x's refcnt is 1.
    say "Before scope exit";
}                             # $x's refcnt drops to 0, so it's freed.
say "After scope exit";

输出:

Before scope exit
Destroyed D=HASH(0x8eff768)
After scope exit

现在,如果您将$x的引用存储在$x所在的范围之外,该怎么办?

use feature qw( say );

{ package D; DESTROY { say "Destroyed $_[0]"; } }

my $ref;
{
    my $x = bless({}, 'D');   # $x's refcnt is 1.
    $ref = \$x;               # $x's refcnt is 2.
    say "Before scope exit";
}                             # $x's refcnt drops to 1, so it's not freed.
say "After scope exit";
$ref = undef;                 # $x's refcnt drops to 0, so it's freed.
say "After clearing reference";

输出:

Before scope exit
After scope exit
Destroyed D=HASH(0x8cc4768)
After clearing reference

在您的代码中,即使在创建创建它的作用域退出后,返回的@a引用也会使@a保持活动状态。这可以通过打印$ttt,然后打印@$ttt来验证。

ARRAY(0x99464b8)
1 2

如果您多次输入该块,则会获得对不同变量的引用,因为my每次都会分配一个新变量*。比较

my @a;
for (1..2) {
    my $x = $_;
    push @a, \$x;
}
say $a[0];  # 1

my @a;
my $x;
for (1..2) {
    $x = $_;
    push @a, \$x;
}
say $a[0];  # 2

* - 实施与此解释不同,但这是一种不会产生明显副作用的优化。