这种代码有什么意义?

时间:2011-08-29 06:57:32

标签: perl

{%{$self->param}}

它进行散列扩展,然后创建另一个散列引用。

{%{$self->param}}$self->param不一样吗?为什么代码打扰这个伎俩?

3 个答案:

答案 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

如果您需要哈希但不参考哈希,也可以省略最后一步。