Perl 中的引用行为与许多程序员在其他编程语言中使用的行为有点不同。例如。考虑这个 Perl 代码:
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
然后你会获得对它的引用:
my $personRef = \%person;
在大多数编程语言中,该语句读作“获取%person 使用的后备存储的内存地址并将其写入$personRef”。在这些语言中,我可以更改%person 本身(而不是它指向的内存),这不会对$personRef 仍然指向与以前相同的内存产生任何影响,它仍然包含与以前相同的值。
但在 Perl 中,此语句读作“让$personRef始终 指向%person 当前使用的内存”。这里的重要关键字始终是,因为这意味着如果您对 %person 进行更改,这些更改也会立即反映在引用中。
因此,当您在 Perl 中执行此操作时:
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
my $personRef = \%person;
%person = (); # <-- Assigns new empty hash!
$person{"name"} = "Jane Doe";
$person{"age"} = 47;
print "$personRef->{'name'}\n";
它实际上会打印“Jane Doe”,因为无论您对%person 做什么,$personRef 将始终指向%person 正在使用的内存,即使您将新的空哈希分配给@ 987654334@,引用现在将指向那个空哈希。
基本上可以说:在 Perl 中,引用不是对值使用的内存的引用,而是对引用这些值的变量的引用。在任何时候使用引用来访问值时,都会使用被引用变量的当前值,并且自引用创建以来这可能已经更改了很多次。
接受的答案通过复制哈希解决了这个问题:
my @people = ();
my %person = ();
$person{"name"} = "John Doe";
$person{"age"} = 34;
push @people, { %person };
%person = ();
$person{"name"} = "Jane Doe";
$person{"age"} = 47;
push @people, { %person };
但是等等,这里复制的哈希值在哪里?嗯,这是 Perl 的魔法。要创建新哈希,您可以使用该语法:
my %hash = (
"name" => "John Doe",
"age" => 34
);
但这只是语法糖,事实上你也可以使用,而不是=>:
my %hash = ("name", "John Doe", "age", 34);
将散列转换为列表时,每个第一个列表项都是一个键,每个第二个列表项都是它的值,所以当从一个列表创建一个散列时,列表值就是这样解释的。现在如果你想直接创建一个哈希的引用,你可以这样写:
my $hashRef = { "name", "John Doe", "age", 34 };
这和写法基本一样:
my $hashRef = { %myHash };
这读作“创建一个新的哈希 ({}),用来自 %myHash 的值填充它,并将对它的引用写入 $hashRef”。这正是这一行发生的事情:
push @people, { %person };
除了新创建的hash的引用直接push到数组上。