在Perl中,所有函数的参数通过数组@_进行处理。当调用子程序时,所有传递的参数都会进入这个数组,并且最初是一个列表,而不是副本,即如果你更改$_[0],你就是在修改原始值。
sub foo { my ($arg1, $arg2) = @_; $arg1 = 10; # 只有局部变量被修改 }
sub bar { my ($array_ref) = @_; push @$array_ref, 42; } my @data = (1,2,3); bar(\@data); # @data 现在是 (1,2,3,42)
my ($a, $b) = @_解包时会创建副本。如果在Perl中将数组传递给函数这样:
myfunc(@arr),在函数内部访问$_[0],那里会是什么?
正确答案: 那里会是数组的第一个元素_值_,而不是指向整个数组的引用!要将数组作为整体对象传递,使用引用:myfunc(\@arr)。
sub print_first { print $_[0], " "; } my @a = qw/foo bar baz/; print_first(@a); # 会输出'foo',而不是数组的引用 print_first(\@a); # 会输出ARRAY(0x...) — 指向整个数组的引用
历史
update_hash(%global)。在函数内部修改了$_[0]。结果 — 只修改了参数数组的局部切片,而全局散列并未被修改。正确的解决方法是传递引用:update_hash(\%global)。历史
myfunc(@arr, %opts)。结果发现部分散列键被数组值替换,而发现这个错误非常困难。历史
在实现递归遍历树时,我们想要修改内部元素。函数接收数组“原样”,而不是引用。它们创建了副本,修改不会影响外部上下文。问题通过替换为引用传递的方式解决。