4

考虑以下简单的代码:

%hash = ('a'=>1,'b'=>2); 
print $hash{'b'};
print "\n",(\%hash)->{'b'};   #used when hashes are passed by reference
                              #to subroutines

正如预期的那样,输出是一对 2。但我在想 $hash{key} 是否是作为 (\%hash)->{key} 完成的引用和取消引用的简写,或者它是达到相同结果的完全不同的途径。

请澄清一下。

4

3 回答 3

1

它们有些不同,因为与许多其他语言不同,所有复杂类型都只能作为引用使用,Perl 具有实际的普通哈希类型和单独的引用类型,可以充当任何其他类型的代理。您可以在perlguts中找到有关此的详细信息。

最后,这两个示例当然都从同一个存储中提取数据,但是第二次调用要长一些,因为它会花时间尽职地创建对普通 HV 的引用,然后按照您的要求将其取消引用。B::Concise您可以使用模块研究有关幕后工作的详细信息。

%hash = ('a'=>1,'b'=>2);
print $hash{'b'};
print (\%hash)->{'b'};

简洁的输出:

$ perl -MO=Concise deref.pl 
t  <@> leave[1 ref] vKP/REFC ->(end)
1     <0> enter ->2
2     <;> nextstate(main 1 deref.pl:1) v:{ ->3
b     <2> aassign[t3] vKS ->c
-        <1> ex-list lKP ->8
3           <0> pushmark s ->4
4           <$> const[PV "a"] s ->5
5           <$> const[IV 1] s ->6
6           <$> const[PV "b"] s ->7
7           <$> const[IV 2] s ->8
-        <1> ex-list lK ->b
8           <0> pushmark s ->9
a           <1> rv2hv[t2] lKRM*/1 ->b
9              <#> gv[*hash] s ->a
c     <;> nextstate(main 1 deref.pl:2) v:{ ->d
i     <@> print vK ->j
d        <0> pushmark s ->e
h        <2> helem sK/2 ->i
f           <1> rv2hv sKR/1 ->g
e              <#> gv[*hash] s ->f
g           <$> const[PV "b"] s ->h
j     <;> nextstate(main 1 deref.pl:3) v:{ ->k
s     <2> helem vK/2 ->t
q        <1> rv2hv[t7] sKR/1 ->r
p           <@> print sK ->q
k              <0> pushmark s ->l
o              <1> refgen lK/1 ->p
-                 <1> ex-list lKRM ->o
l                    <0> pushmark sRM ->m
n                    <1> rv2hv[t6] lKRM/1 ->o
m                       <#> gv[*hash] s ->n
r        <$> const[PV "b"] s ->s
deref.pl syntax OK
于 2012-05-23T11:31:03.387 回答
1

但我在想 $hash{key} 是否是作为 (\%hash)->{key} 完成的引用和取消引用的简写,或者它是达到相同结果的完全不同的途径。

不,$hash{key} 只是对 %hash 的简单访问,就像 $array[0] 是对 @array 的简单访问一样。但是 \%hash 是对 %hash 的引用,因此需要取消引用才能访问它。语法(\%hash)->{key}将简写为:

do { my $temp_ref = \%hash; $temp_ref->{key} } 

但是如果你有 %hash , $hash{key} 可以很好地工作而没有无用的引用/取消引用。散列和数组(通常)通过引用传递给子例程,因为 perl 的列表展平使得很难传递多个。(一个常见的例外是实现命名参数的函数。)

有关 perl 中引用的完整说明,请参见perldoc perreftutperldoc perlref

于 2012-05-23T13:48:38.583 回答
0

Perl 5 中的印记 ($ % @) 发生了变化,因为它反映了正在访问的值。

my @a = (10, 20, 30);  # Whole array
print $a[1];           # Single scalar element of @a
my %h = (a=>1, b=>2);  # Whole hash
print $h{a};           # Single scalar value from %h

引用都以“$”开头的原因是它们都是标量。这有帮助吗?

于 2012-05-23T11:16:17.823 回答