12

特殊数组 ,@_其中存在传递给函数的所有参数,实际上是传递参数的别名。因此,我们直接对这个特殊数组所做的任何更改也@_将反映在 main 中。这很清楚。

#!/usr/bin/perl

use warnings;
use strict;

$\="\n";

sub func {
        print \@_;
        $_++ for(@_);
}

my @arr=(2..4);
print \@arr;
func(@arr);
print "@arr";

对于上面的程序,我希望 和 的引用@arr指向@_同一个位置,因为它是一个别名。但事实并非如此。

在运行上述:

ARRAY(0x1b644d0)
ARRAY(0x1b644e0)
3 4 5

如果他们指向 2 个不同的位置,所做的更改如何@_反映在@arr

我看错了吗?请指教。

4

2 回答 2

17

这可能会回答你的问题:

use warnings;
use strict;

$\="\n";

sub func {
        print \@_;
        $_++ for(@_);
        print \$_ for @_; 
}

my @arr=(2..4);
print \@arr;
func(@arr);
print "@arr";
print \$_ for @arr;

输出

ARRAY(0x17fcba0)
ARRAY(0x1824288)
SCALAR(0x17fcc48)
SCALAR(0x18196f8)
SCALAR(0x1819710)
3 4 5
SCALAR(0x17fcc48)
SCALAR(0x18196f8)
SCALAR(0x1819710)

如您所见,各个参数具有相同的地址,但容器不同。如果你将一个项目推到@_infunc@arr不会改变(所以你可以shift在 中做funct)。因此,每个参数都是一个别名,数组元素作为单独的项目传递。@_包含传递给子例程的所有项目。如果要修改数组参数,则需要通过引用传递它。

于 2013-03-07T05:00:54.613 回答
11

@_没有别名;它的元素是。

请记住

func(@arr);

是相同的

func($arr[0], $arr[1], ...);

因为唯一可以传递给 sub 的是标量列表,而数组在列表上下文中计算为其元素的列表。

所以这意味着

func(@arr);

基本上是一样的

local @_;
alias $_[0] = $arr[0];
alias $_[1] = $arr[1];
...
&func;

更改 的元素@_会更改 的元素@arr,但添加和删除 的元素@_不会改变@arr,因为它们是不同的数组。

>perl -E"@a=(4..6); sub { $_[0] = '!';        say @_; }->(@a); say @a;"
!56
!56

>perl -E"@a=(4..6); sub { splice(@_,0,1,'!'); say @_; }->(@a); say @a;"
!56
456
于 2013-03-07T05:37:56.743 回答