{%{$self->param}}
它进行散列扩展,然后创建另一个散列引用。
但{%{$self->param}}
与$self->param
不一样吗?为什么代码打扰这个伎俩?
答案 0 :(得分:15)
它复制哈希。请考虑以下代码段:
use Data::Dumper;
my $foo = { a => 1, ar => [1] };
my $bar = {%$foo};
$bar->{b} = 2;
push @{$bar->{ar}}, 4;
print Dumper $foo;
print Dumper $bar;
打印
$VAR1 = {
'a' => 1,
'ar' => [
1,
4
]
};
$VAR1 = {
'a' => 1,
'b' => 2,
'ar' => [
1,
4
]
};
因此,您可以看到副本很浅:标量被复制,即使它们是引用。引用的对象是相同的(在此示例中为ar
引用的数组)。
答案 1 :(得分:8)
尽管{%{$self->param}}
和$self->param
都是对哈希的引用,但它们并不是指存储在同一位置的哈希。
第一个表达式将$self->param
解除引用到哈希,并返回对匿名哈希的引用。在外括号内,%{$self->param}
实际上是临时展开和复制的,然后返回对此临时副本的引用,而不是旧哈希。
答案 2 :(得分:8)
此代码实际上创建了一个副本哈希(键和值的浅表副本,但不是深层副本),返回引用并返回对它的引用。
如果某个子类返回对散列的引用并且您在其中更改了某些内容,则实际上您正在更改原始散列中的值。为避免这种情况,我们有时需要在进行任何更改之前复制整个哈希(或数组)。
以下是示例:
sub get_hashref {
my $hashref = shift;
return $hashref;
}
my %hash = (foo => 'bar');
my $ref = get_hashref(\%hash);
$ref->{foo} = 'baz'; # Changes 'foo' value in %hash
print "Original 'foo' now is: $hash{foo}\n"; # 'baz'
print "Ref's 'foo' now is: $ref->{foo}\n"; # 'baz'
# But!
$ref = {%{ get_hashref(\%hash) }};
$ref->{foo} = 42; # No changes in %hash
print "Original 'foo' now is: $hash{foo}\n"; # 'baz'
print "Ref's 'foo' now is: $ref->{foo}\n"; # '42'
为了更好地理解,{%{ $self->param }}
可以扩展为:
my $ref = $self->param; # Ref to original hash
my %copy = %{$ref}; # Copies keys and values to new hash
my $ref_to_copy = {%copy}; # get ref to it
如果您需要哈希但不参考哈希,也可以省略最后一步。