my、our和local

在Perl中,my、our和local都可以用来声明变量:

my $a;     my ($x, $y);
our $a;    our ($x, $y);
local $a;  local ($x, $y);

它们声明的变量在作用域内存活的时间以及操作的目标数据不同:

  • my声明的变量和其指向的内存都在自己的作用域内生效,退出作用域后,变量失效,其指向的内存被回收
  • our声明的变量是私有变量,但其操作的内存数据,或者说它指向的是同名全局变量对应的内存数据,退出作用域后,该私有变量失效,但在作用域内修改的全局数据会直接写入同名全局变量对应的内存并持久生效。
    • 实际上,our声明的就是私有全局变量,如果已经存在our声明的全局变量,再次our声明该变量将给出警告
  • local声明的变量是私有变量,但其操作的内存数据,或者说它指向的是同名全局变量对应的内存数据,它只是临时操作全局同名变量的数据。在作用域内修改全局数据时,其他地方(比如多线程时)也可以看到对该数据的临时修改,当退出作用域后,该私有变量失效,其临时操作的数据被全局原始数据重新覆盖
    • 实际上,local会先找到全局同名变量,再建立它们的关系,如果找不到全局同名变量,将报错

因此:

## my
my $a = 33;
{
  # 声明私有变量$a,但赋值表达式右边的$a是全局变量
  my $a = $a + 1;
  say "$a";  # 输出私有变量$a:34
}
say "$a";  # 输出全局变量$a:33

## our
our $b = 33;  # 声明全局$b
{
  our $b = $b + 1;  # 给出警告,第二次声明全局$b,它们指向同一个位置
  say "$b";
}
say "$b";

## local
local $c = 33;
my $d = 33;
our $e = 33;
{
  local $c = $c + 1;  # 报错,找不到全局$c变量
  local $d = $d + 1;  # 报错,找不到全局$d变量
  local $e = $e + 1;  # 正确,关联全局$e
  say $e;  # 34
} # 退出该作用域之前,任何地方看到的全局$e都是此处修改后的值
say $e;  # 33