什么时候返回数组或哈希,什么时候只引用?

Jim*_*Jim 4 arrays perl hash reference function

我对以下内容感到困惑.
有时候我会看到这样的例子:

my %hash = get_data();

sub get_data {
    my %data = ();
    # do processing
    return %data;
}
Run Code Online (Sandbox Code Playgroud)

与数组类似.

my @arrays = get_data();

sub get_data {
    my @data = ();
    # do processing
    return @data;
}
Run Code Online (Sandbox Code Playgroud)

我原本以为你不能从函数返回数组或哈希只引用它们.
所以我不明白有什么区别,我们何时应该优先于另一方?
它与垃圾收集或我们选择的数据副本有太大关系吗?

Mic*_*man 12

严格地说,您不能从Perl子例程返回数组或哈希.Perl子例程返回列表.列表类似于数组,因为它们是值的序列,但它们不是数组.数组是变量.列表是无名,不可变和瞬态数据结构,用于传递和返回值,初始化数组和散列等.这是一个有点微妙的点,但是一个重要的.

当你写的时候return @data你没有返回@data阵列; 您将返回其包含的值列表.同样,return %data返回哈希中包含的键/值对的列表.这些值可用于初始化另一个数组或散列,这正是您的示例中发生的情况.初始化的数组/散列包含子例程使用的副本的(浅)副本.

要"返回"数组或散列,必须返回对它的引用.例如return \@datareturn \%data.这样做会返回对变量本身的引用.修改它也会影响原始数组,因为它是相同的存储.

sub是否应该将数组/散列作为列表(副本)或引用返回是编程决策.对于总是返回具有位置意义的N值(例如localtime内置)的subs,返回列表是有意义的.对于返回任意大型列表的subs,通常更好的是返回引用,因为它更有效.

一个sub甚至可以根据使用它的方式来决定返回什么wantarray.这让来电者决定他们想要什么.

sub get_data {
    my @data;
    ...
    return wantarray ? @data : \@data;
}

my $aref  = get_data(); # returns a reference
my @array = get_data(); # returns a list
Run Code Online (Sandbox Code Playgroud)

  • @吉姆:对。通过返回引用,您将获得数组的单个副本,只要该副本至少有一个引用,该副本就会持续存在。返回列表会导致数组的多个副本,但子副本可立即用于GC。 (2认同)