Perl:特殊数组@_真的不是别名吗?

Gur*_*uru 12 perl

@_传递给函数的所有参数都存在的特殊数组实际上是传递的参数的别名.因此,我们直接对这个特殊数组进行的任何更改都@_将反映在主要数据中.这很清楚.

#!/usr/bin/perl

use warnings;
use strict;

$\="\n";

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

my @arr=(2..4);
print \@arr;
func(@arr);
print "@arr";
Run Code Online (Sandbox Code Playgroud)

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

在运行上面:

ARRAY(0x1b644d0)
ARRAY(0x1b644e0)
3 4 5
Run Code Online (Sandbox Code Playgroud)

如果他们指向两个不同的位置,那么所做的更改@_是如何反映的@arr

我看错了吗?请指教.

per*_*eal 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;
Run Code Online (Sandbox Code Playgroud)

产量

ARRAY(0x17fcba0)
ARRAY(0x1824288)
SCALAR(0x17fcc48)
SCALAR(0x18196f8)
SCALAR(0x1819710)
3 4 5
SCALAR(0x17fcc48)
SCALAR(0x18196f8)
SCALAR(0x1819710)
Run Code Online (Sandbox Code Playgroud)

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


ike*_*ami 11

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

记住这一点

func(@arr);
Run Code Online (Sandbox Code Playgroud)

是相同的

func($arr[0], $arr[1], ...);
Run Code Online (Sandbox Code Playgroud)

因为唯一可以传递给sub的是标量列表,并且数组在列表上下文中求值为其元素列表.

这意味着

func(@arr);
Run Code Online (Sandbox Code Playgroud)

基本上是一样的

local @_;
alias $_[0] = $arr[0];
alias $_[1] = $arr[1];
...
&func;
Run Code Online (Sandbox Code Playgroud)

更改元素@_会改变元素@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
Run Code Online (Sandbox Code Playgroud)