重申这个问题,为什么数组中重复的哈希条目引用了Perl中的第一个条目?如果我弄错了,请更正我的术语,但是当我将相同的哈希引用推送到具有以下代码的数组中时:
use strict;
use warnings;
use Data::Dumper qw(Dumper);
my @array;
my %hash = (foo => 'foo', bar => 'bar');
for (1..3) {
push @array, \%hash;
}
print Dumper @array;
Run Code Online (Sandbox Code Playgroud)
我得到以下结果:
$VAR1 = {
'bar'=> 'bar',
'foo'=> 'foo'
};
$VAR2 = $VAR1;
$VAR3 = $VAR1;
Run Code Online (Sandbox Code Playgroud)
我希望看到以下结果:
$VAR1 = {
'bar'=> 'bar',
'foo'=> 'foo'
};
$VAR2 = {
'bar'=> 'bar',
'foo'=> 'foo'
};
$VAR3 = {
'bar'=> 'bar',
'foo'=> 'foo'
};
Run Code Online (Sandbox Code Playgroud)
这种行为是因为Perl的基本概念还是因为Data::Dumper?
基本上你已经自己说过了(强调我的).
如果我弄错了,请更正我的术语,但是,当我将相同的哈希引用推送到具有下面代码的数组中时
那是因为你推入了对哈希的引用.在循环的每次迭代中,它始终是相同的散列,因此每个新引用都转到相同的散列.
如果您使用数据::打印机的p,输出如下,我觉得这不是更清晰的数据::自卸车之一.
[
[0] {
bar "bar",
foo "foo"
},
[1] var[0],
[2] var[0]
]
Run Code Online (Sandbox Code Playgroud)
很明显,它指的是同样的事情.现在,如果您运行此代码:
for (@array) {
say $_;
}
Run Code Online (Sandbox Code Playgroud)
输出将是同一地址的三倍.
HASH(0x2755150)
HASH(0x2755150)
HASH(0x2755150)
Run Code Online (Sandbox Code Playgroud)
参考的整个想法是引用相同的东西.这是一个非常强大的工具,因为这样可以节省内存.如果你$hash确实不只是一个很小的哈希值,而是一个大对象(比方说,一个WWW ::机械化对象,可容纳解析的HTML文档),周围路过这将是超贵.
但是通过引用,获得它的每一段代码都可以共享它.这样更有效率.
有关这方面的更多信息,您应该阅读perlref和perlreftut.
但是,如果您需要副本,则需要构建自己的哈希引用,而不是引用已有的哈希.这就是@toolic在评论中所说的.
my %hash = (foo => 'foo', bar => 'bar');
for (1..3) {
push @array, { %hash };
}
Run Code Online (Sandbox Code Playgroud)
如果你有一个现有的参考,并且你想要一个副本,首先取消引用它.
my $ref = { foo => 'bar' };
my $shallow_copy = { %{ $ref } };
Run Code Online (Sandbox Code Playgroud)
如果您需要更深层次的副本,请查看此答案.