【问题标题】:Modifying array in subroutine在子程序中修改数组
【发布时间】:2012-04-17 06:14:33
【问题描述】:

我有一些代码不能按我预期的方式工作,如果能帮助我弄清楚如何让它按我预期的方式工作,我将不胜感激。

我想使用子程序来修改输入数组。我想如果我传入对数组的引用,我对它所做的任何更改也会反映在调用者的版本中。但它显然不是那样工作的。


my @test_array = qw (zero one two three);

shift_array(\@test_array);
print "POST SUBROUTINE: $test_array[0]\n";

sub shift_array {
    my @array = @{(shift)};
    shift @array;
    print "AFTER SHIFT IN SUB: $array[0]\n";
}

打印出来:

换班后:一 发布子程序:零

我预计它会打印两次one

所以我的问题有两个:

1) 为什么它的行为不像我认为的那样?传递对数组的引用会创建数组的副本吗?

2) 我如何获得我所期望的行为?如何让子例程从调用者的输入数组副本的前面滑出一个或多个元素?

提前感谢您提供的任何见解。

【问题讨论】:

    标签: perl


    【解决方案1】:

    因为my @array 是您将取消引用的原始数组分配给的新数组。这是一个副本。

    改为这样做:

    sub shift_array {
        my $array = shift;
        shift( @$array );
    }
    

    编辑:我最初说取消引用它会产生问题,但使用@$array 仍然是取消引用它。正如@mob 指出的那样,分配变量是创建新数组而不是更新现有引用的原因。

    【讨论】:

    • 哇。这是我不明白的细微差别。谢谢!
    • 请注意,对于 perl 5.14+,您可以在 sub 中写入 shift $array 并且取消引用会自动发生。
    【解决方案2】:

    这是 Perl 原型有用的(极少数)案例之一。

    #!/usr/bin/perl
    
    use strict;
    use warnings;
    
    # Prototype forces the first argument to be a reference to an array    
    sub shift_array (\@) {
      my $array = shift;
      shift(@$array);
      print "AFTER SHIFT IN SUB: @$array[0]\n";
    }
    
    my @test_array = qw (zero one two three);
    
    shift_array(@test_array);
    print "POST SUBROUTINE: $test_array[0]\n";
    

    【讨论】:

      【解决方案3】:

      我更喜欢在使用数组引用时更加一致,以尽量减少歧义:

      #!/usr/bin/perl
      use strict;
      use warnings;
      
      my @test_array = qw (zero one two three);
      
      shift_array(\@test_array);
      print "POST SUBROUTINE: $test_array[0]\n";
      
      sub shift_array {
          my $ref = shift;
          shift @$ref;
          print "AFTER SHIFT IN SUB: ${$ref}[0]\n";
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-01-26
        • 2018-11-26
        • 2019-05-08
        • 1970-01-01
        • 1970-01-01
        • 2016-10-20
        • 1970-01-01
        相关资源
        最近更新 更多