Perl:从子例程返回后,哈希值发生了变化

时间:2013-11-08 18:42:55

标签: perl hash return-value subroutine

我正在使用perl中的哈希,但不明白为什么哈希值会在以下内容中发生变化:

use strict;

sub test
{
    my ($value_ref) = @_;
    my %value = %$value_ref;
    $value{'abc'}{'xyz'} = 1;
}

my %hash;
$hash{'abc'}{'xyz'} = 0;
test (\%hash);
print "$hash{'abc'}{'xyz'}\n";

以上返回1,为什么它不像这样返回0?

use strict;

sub test
{
    my ($value_ref) = @_;
    my %value = %$value_ref;
    $value{'abc'} = 1;
}

my %hash;
$hash{'abc'} = 0;
test (\%hash);
print "$hash{'abc'}\n";

我想它与我如何传递%hash有关。我错过了什么?

2 个答案:

答案 0 :(得分:7)

您收到的结果不正确,因为当您使用my %value = %$value_ref;进行哈希的复制时,您只能获得顶级密钥。使用键'xyz'的第二级是实际存储值的级别,因此对引用的任何更改都会被转移。当您需要副本时,您正在执行副本。

幸运的是,有一个CPAN模块!

use strict;
use Storable qw(dclone);

sub test
{
    my ($value_ref) = @_;
    my %value = %{ dclone($value_ref) };
    $value{'abc'}{'xyz'} = 1;
}

my %hash;
$hash{'abc'}{'xyz'} = 0;
test (\%hash);
print "$hash{'abc'}{'xyz'}\n"; # prints 0

答案 1 :(得分:3)

这是因为哈希的“第二级”(IOW:键'abc'的值)本身就是一个哈希引用。当您在作业中复制$value_ref引用的哈希内容时:

my %value = %$value_ref;

......这只是做一个“浅薄”的副本。

当您修改键'xyz'的值时,您正在修改传递给子的原始结构中的相同哈希。