Perl: ссылка на массив против анонимного массива

это может быть глупый вопрос... Следующий код выводит содержимое @arrayref и @arraycont соответственно. Обратите внимание на разницу между ними и способ присвоения им значений. Я знаю, что делает анонимный массив, но может ли кто-нибудь объяснить, почему есть разница?

большое спасибо.

@arrayref = ();
@array = qw(1 2 3 4);
$arrayref[0] = @array;
@array = qw(5 6 7 8);
$arrayref[1] = @array;
print join "t", @{$arrayref[0]}, "n";
print join "t", @{$arrayref[1]}, "n";

@arraycont = ();
@array = qw(1 2 3 4);
$arraycont[0] = [@array];
@array = qw(5 6 7 8);
$arraycont[1] = [@array];
print join "t", @{$arraycont[0]}, "n";
print join "t", @{$arraycont[1]}, "n";

выходы

5   6   7   8   
5   6   7   8   
1   2   3   4   
5   6   7   8   

3 ответов


Это создает мелкий копию массива:

$arraycont[0] = [@array];

а это просто создает ссылку на него:

$arrayref[0] = \@array;

так как вы позже измените массив:

@array = qw(5 6 7 8);

arrayref все еще указывает на то же расположение массива в памяти, и поэтому при разыменовании в операторах печати он печатает текущие значения массива 5 6 7 8.


в первом блоке хранится адрес @ array. Ссылки вроде 'live streaming', вы получаете текущее состояние. Поэтому, если вы создадите ссылку на @ array, как \@array, когда вы де-ссылки вы всегда будете получать то, что @ array точки в момент отсчета. Когда вы де-см. @ array было (5 6 7 8)

когда вы [@array] его как запись в прямом эфире на диске. Поэтому, когда вы (re)воспроизводите записанный контент, вы получаете то, что было транслировалось во время записи. Поэтому, когда вы ссылаетесь $arraycont[0] вы получаете @ array был в момент копирования, то есть
(1 2 3 4)


вы сделали сохраненные ссылки на один массив в обоих $arrayref[0] и $arrayref[1]. Вы должны были использовать разные массивы.

my @refs;

my @array1 = qw(1 2 3 4);
push @refs, \@array1;

my @array2 = qw(5 6 7 8);
push @refs, \@array2;

на практике my выполняется в каждом проходе цикла, создавая каждый раз новый массив.

my @refs;
while ( my @row = get() ) {
   push @refs, \@row;
}

в редких случаях, когда вам нужно клонировать массив, вы можете использовать:

use Storable qw( dclone );

push @refs, [ @row ];       # Shallow clone
push @refs, dclone(\@row);  # Deep clone