是否创建了新的“哈希”

时间:2016-11-23 15:19:55

标签: perl hash

以下是我设置的一些测试,以帮助我理解哈希和参考:

my %record1 = ( "Name"    => "My Name");
my %record2 = %record1;
my $record3 = \%record1;
$record1{'test'}= "yes";
print \%record1 ;
print "\n";
print %record1;
print "\n";
print \%record2;
print "\n";
print %record2;
print "\n";
print %$record3;
  • record2是record1的“浅层”副本?
  • record3是record1的哈希引用(指针)?

sub some_func{
    %some_hash = ();
...
    return %some_hash;
}
%some_hash2 = some_func(); # created new hash? 

sub some_func2{
    %some_hash = ();
...
    return \%some_hash
}
$some_hash_ref3 = some_func2(); # ref to original hash? 

2 个答案:

答案 0 :(得分:1)

首先:

#!/usr/bin/env perl

use strict;
use warnings;

use Scalar::Util qw( refaddr );

my %record1 = ("Name" => "My Name");

printf "Address of %%record1 = %d\n", refaddr \%record1;

my %record2 = %record1;

printf "Address of %%record2 = %d\n", refaddr \%record2;

my $record3 = \%record1;

printf "Address of hash pointed to by \$record3 = %d\n", refaddr $record3;

输出:

Address of %record1 = 140595226123056
Address of %record2 = 140595226215352
Address of hash pointed to by $record3 = 140595226123056

这表明%record1%record2是不同的哈希值,而$record3指向%record1

接下来,

sub some_func{
    %record1 = ();
    return %record1
}
%record2 = some_func(); # created new hash? 

哎哟!您正在清除%record1哈希(即从中删除所有键和值)。 %record1存在于此函数之外。这个函数唯一返回的是一个空列表。

然后%record2 = some_func()会做两件事:在函数体中,它会清除%record1。并且,因为它返回空列表,它还会清除%record2中的所有键和值。

现在,添加

printf "Address of %%record1 = %d\n", refaddr \%record1;

printf "Address of %%record2 = %d\n", refaddr \%record2;

%record2 = some_func()之后,您会发现%record1%record2仍然是相同的哈希值。但是,它们都是空的:

use Data::Dumper;
print Dumper $_ for \(%record1, %record2);

输出:

$VAR1 = {};
$VAR1 = {};

最后,请注意:

$record3 = some_func(); # ref to original hash?

我们已经确定some_func返回空列表。但是,因为您要将返回值分配给标量,所以您在返回的列表上强制使用标量上下文。 $record3将获取返回列表中的最后一个元素,而不是返回列表中的元素数。在这种情况下,这将是undef,因为返回的列表中没有元素。在数字上下文中,undef将被解释为0。 (感谢David Cross抓住我的阵列/列表混乱)。

$record3不再是对任何内容的引用。

答案 1 :(得分:1)

  

record2是一个“浅薄的”' record1的副本?

是的,%record1%record2是不同的哈希值,%record2包含%record1内容的(浅)副本。

  

record3是record1的哈希引用(指针)?

是的,$record3包含对哈希%record1的引用。

$ perl -e'
   my %record1 = ( "Name" => "My Name");
   my %record2 = %record1;
   my $record3 = \%record1;
   CORE::say( \%record1 == \%record2 ? "same" : "different" );
   CORE::say( \%record1 == $record3  ? "same" : "different" );
'
different
same

请注意,虽然引用和指针非常相似,但它们并不相同。引用是一个指针,您无法在其上执行算术运算。 Perl只有引用。

  

创建了新哈希?

没有。 my创建新变量,但您没有使用my。首次遇到对它们的引用(因此在编译时而不是在调用%some_hash期间)时会创建未声明的变量,例如some_func

此外,some_func没有返回哈希值。除了潜艇的标量之外,不可能返回任何东西。 (另外,除了标量之外,不可能将任何内容传递给子。)some_func实际上会返回%record1内容,这是一个空列表情况下。

  

引用原始哈希?

是。返回的标量(对%some_hash的引用)被复制到$some_hash_ref3,因此$some_hash_ref3包含对%some_hash的引用。