12

関数に渡されたすべての引数が存在する特別な配列 は@_、実際には渡された引数のエイリアスです。したがって、この特別な配列に直接加えた変更は@_、メインにも反映されます。これは明らかです。

#!/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)

ご覧のとおり、個々の引数のアドレスは同じですが、コンテナーは同じではありません。にアイテムを押してもは変化@_しません (だからでできます)。したがって、各引数はエイリアスであり、配列要素は個別の項目として渡されます。サブルーチンに渡されたすべての項目が含まれます。配列引数を変更する場合は、参照渡しする必要があります。func@arrshiftfunct@_

于 2013-03-07T05:00:54.613 に答える
11

@_エイリアスされていません。その要素は。

覚えておいてください

func(@arr);

と同じです

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

サブルーチンに渡すことができる唯一のものはスカラーのリストであり、配列はリスト コンテキスト内の要素のリストに評価されるためです。

つまり、

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 に答える