代码是否正确?
my $ttt = eval {
my @a=(1,2);
return \@a;
};
print @$ttt[1]. "\n";
我想,eval块是在飞行中评估的,并且在执行后不存在。该决定是否存在任何缺陷?
答案 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
* - 实施与此解释不同,但这是一种不会产生明显副作用的优化。