6

从解释器的 POV 来看,以下程序之间有什么区别:

#!/usr/bin/perl -w

use strict;

for (1..10000000) {
    my $jimmy = $_**2;
}

#!/usr/bin/perl -w

use strict;

my $jimmy;
for (1..10000000) {
    $jimmy = $_**2;
}

第一个程序的“时间”报告:

real    0m1.519s
user    0m1.513s
sys     0m0.004s

第二个:

real    0m1.023s
user    0m1.012s
sys     0m0.002s
4

5 回答 5

10

Perl 中的my声明有两个主要效果:一个编译时的(其中它在包含子的暂存器上分配一个插槽,并确保在适当范围内对该名称的所有引用都解析到该特定的暂存器插槽)和一个运行时的(其中它重置值那个垫槽到undef,或者如果你写了某个特定的值my $var = foo)。

编译时部分当然具有零摊销运行时成本,但运行时部分在每次执行通过 my 声明时运行一次。正如其他人所指出的那样,您的两个示例具有不同的性能,因为它们通常具有不同的语义——一个每次通过循环都清除变量,而另一个则没有。

于 2010-07-23T20:28:49.530 回答
3

由于您给出的示例程序并没有真正做任何事情,因此很难给您一个具体的理由说明为什么一种类型的声明会比另一种更好。正如许多其他海报所指出的那样,在循环中声明变量每次都会创建一个新变量。在您的示例中,创建是多余的,但请考虑使用闭包的以下示例。

my @closures;
my $jimmy;

for (1 .. 10) {
    $jimmy = $_** 2;
    push @closures, sub {print "$jimmy\n"};
}

和这个:

my @closures;

for (1 .. 10) {
    my $jimmy = $_** 2;
    push @closures, sub {print "$jimmy\n"};
}

在每种情况下,代码都会构建一系列代码引用,但在第一个示例中,由于所有代码引用都引用相同,因此$jimmy每个代码引用在调用时都会打印 100。在第二个示例中,每个代码 ref 将打印不同的数字(1、4、9、16、25,...)

所以在这种情况下,时间差异并不重要,因为这两个代码块做的事情非常不同。

于 2010-07-23T21:33:26.610 回答
2

第一个循环尝试为循环的每次迭代进行变量声明,并可能导致不必要的处理时间。

诚然,它并不多,但是这些东西会随着时间的推移而增加,而且在技术上它更慢,因为每次迭代执行的指令更多。

于 2010-07-23T19:15:23.347 回答
1

嗯,有一个问题是你在每次迭代中声明一个新变量。

第二,还有一个更大的范围问题。

尝试在每一个之后添加这一行for,看看会发生什么:

print $jimmy;

并且,也试试这个:

my $jimmy;
for (1..10000000) {
    my $jimmy = $_**2;
}
print $jimmy;

更详细一点:

A my 将列出的变量声明为封闭块、文件或 eval 的本地(词法)变量。如果列出了多个值,则必须将列表放在括号中。

http://perldoc.perl.org/functions/my.html

您可能会发现这也是一本有用的读物​​:

http://perldoc.perl.org/perlsub.html#Private-Variables-via-my%28%29

于 2010-07-23T19:18:36.170 回答
0
  1. 在循环外声明my会导致声明发生一次。在声明期间,perl 为该变量保留内存。

  2. 在循环内部声明会导致声明my在循环的每个间隔发生。

my是 Perl 对在本地声明变量的答案 -local用于其他用途,与在 C 中的含义不同。当您在循环内声明变量时,它在循环块的本地范围内声明,其中该块在每个间隔开始/结束。undef不仅声明了变量,而且还可以在块的末尾清理(取消引用和/或设置为)(尽管这与 Perl 版本不同)。

在循环块之外声明的变量被认为是“全局的”(不是字面意思,而是循环块的意义)。这些变量重复使用它们的内存位置,而不必搜索新地址。

于 2010-07-23T23:42:33.273 回答