имеет значение область ссылки на массив в этом примере кода - PullRequest
3 голосов
/ 20 февраля 2012
#!/usr/bin/perl

    A();
    B();

    sub A {
        my @array = qw(value_1 value_2);
        $array_ref = \@array;
    }

    sub B {
        foreach my $i ( @{$array_ref} ) {
            print "Array Value: $i \n";
        }
    }

Поскольку массив объявлен с использованием ключевого слова 'my', может ли быть потеряна ссылка на массив?Может ли кто-нибудь проинформировать меня об этом.

Ответы [ 3 ]

7 голосов
/ 20 февраля 2012

Нет, область действия переменной истекает, но не адрес памяти. Данные останутся.

Разве это не то, что вы могли бы просто попробовать? =) Я просто скопировал / вставил твой код и попробовал его, и он работал нормально.

Однако для правильной инкапсуляции вы должны вместо этого вернуть массив ref:

B(A());
# Or
my $aref = A();
B($aref);

sub A {
        my @array = qw(value_1 value_2);
        return \@array;
}

sub B {
    my $array_ref = shift;
    foreach my $i ( @$array_ref ) {
        print "Array Value: $i \n";
    }
}
3 голосов
/ 20 февраля 2012

Я определенно рекомендую использовать

use strict;

в скриптах Perl (поместите это в самое начало). В этом случае он будет жаловаться на то, что $ array_ref объявлен глобальным. И это, вероятно, основной источник путаницы: вы используете $ array_ref, не объявляя его каким-либо образом, поэтому он рассматривается как глобальная переменная.

Содержимое самого массива сохраняется, потому что на него ссылается эта самая переменная, поэтому счетчик ссылок остается больше 0 (perl использует подсчет ссылок внутри, чтобы отслеживать, когда удалять переменные).

Конечно, рекомендуется подход, подобный показанному в сообщениях TLP (без глобальных).

0 голосов
/ 20 февраля 2012

На самом деле есть очень веская причина использовать my в этом примере.
Вы действительно хотите, чтобы переменная создавалась каждый раз при выполнении подпрограммы, в противном случае вы бы изменили значениячто вы получили ранее.

use strict;
use warnings;
use 5.10.1;

my @array;
sub A{
  push @array, scalar @array; # add the length of @array to the end
  return \@array;
}

my @list;

for( 'A'..'D' ){
  my $current = A();
  push @list, $current;
  say join ' ', @$current;
}

say '';

say join ' ', @$_ for @list;
0
0 1
0 1 2
0 1 2 3

0 1 2 3
0 1 2 3
0 1 2 3
0 1 2 3

Обратите внимание, что каждая копия @array идентична.


Именно поэтому вам нужна новая копия для каждого раза, когда подпрограмманазывается.

use strict;
use warnings;
use 5.10.1;

sub A{
  state $iter = 0;
  my @array;
  push @array, 0..$iter++;
  return \@array;
}

my @list;

for( 'A'..'D' ){
  my $current = A();
  push @list, $current;
  say join ' ', @$current;
}

say '';

say join ' ', @$_ for @list;
0
0 1
0 1 2
0 1 2 3

0
0 1
0 1 2
0 1 2 3
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...