Perl语言的指针地址、引用、解引用以及多维的实现
Perl语言的指针地址、引用、解引用以及多维的实现

Perl语言的指针地址、引用、解引用以及多维的实现

引用简介

引用就是指针,可以指向变量、数组、哈希表(也叫关联数组)甚至子程序。Pascal或C程序员应该对引用(即指针)的概念很熟悉,引用就是某值的地址,对其的使用则取决于程序员和语言的规定。在Perl中,可以把引用称为指针,二者是通用的,无差别的。引用在创建复杂数据方面十分有用。
本章中,简单变量指像$pointer这样的变量,$pointer仅含一个数据项,其可以为数字、字符串或地址。
任何简单变量均可保存硬引用。因为数组和哈希表含有多个简单变量,所以可以建立多种组合而成的复杂的数据结构,如数组的数组、哈希表的数组、子程序的哈希表等等。只要你理解其实只是在用简单变量在工作,就应该可以正确的在最复杂的结构中正确地解除引用。

引用、解引用

一般使用反斜线(\)创建变量为一个新的引用,用数据的原始数据类型对应的符号进行解引用。

标量引用

perl -e ' my $scalar=22; print"$scalar\n"; my $scalar_pointer=\$scalar; print"$scalar_pointer\n"; print "${$scalar_pointer}\n";  '
22
SCALAR(0xc96be0)
22

定义一个标量$scalar,值为22。
用\$scalar进行引用,引用的结果是一个地址:SCALAR(0xc96be0),把这个地址赋值给标量$scalar_pointer。(这里地址是随机的,每次运行都不一样)
使用${$scalar_pointer}可以对地址解引用。

数组引用

关于Perl语言应该记住的最重要的一点可能是:Perl中的数组和哈希表始终是一维的。因此,数组和哈希表只保存标量值,不直接存贮数组或其它的复杂数据结构。数组的成员要么是数(或字符串)要么是引用。

perl -e ' 
my @array=qw(abcd efgh 345 ju78 67jd); 
my $array_pointer=\@array ;
print"@array\n";
print"$array_pointer\n";
print"@{$array_pointer}\n"; 
print"${$array_pointer}[0]\n";
print"$array_pointer->[0]\n";  '

abcd efgh 345 ju78 67jd
ARRAY(0x2502c40)
abcd efgh 345 ju78 67jd
abcd
abcd

定义了一个数组@array,存放“abcd efgh 345 ju78 67jd”内容。
用\@array进行引用,引用的结果是一个地址:ARRAY(0x2502c40),把这个地址赋值给标量$array_pointer。(这里地址是随机的,每次运行都不一样)
使用@{$array_pointer}可以对地址解引用,可以使用${$array_pointer}[0]或者$array_pointer->[0]格式直接从指针地址调用这个数组内的元素。
其中${$array_pointer}[0]可以写成@{$array_pointer}[0],但是不符合语法规范,不建议使用。还有一些花括号省略后不影响结果,但是建议规范书写。

哈希引用

哈希的引用和数组类似。

perl -e '
my %hash=("name"=>"wangzq","age"=>"18","tel"=>"123456","add"=>"shanghai");
my $hash_pointer=\%hash;
print"$hash_pointer\n";  
print"${$hash_pointer}{tel}\n"; 
print"$hash_pointer->{tel}\n"; '

HASH(0x189dc60)
123456
123456

定义了一个哈希%hash,存放了(“name”=>”wangzq”,”age”=>”18″,”tel”=>”123456″,”add”=>”shanghai”)四个键值对。
用\%hash进行引用,引用的结果是一个地址:HASH(0x189dc60),把这个地址赋值给标量$hash_pointer。(这里地址是随机的,每次运行都不一样)
使用%{$hash_pointer}可以对地址解引用(例子中没有写,因为哈希内容不能直接打印),可以使用${$hash_pointer}{tel}或者$hash_pointer->{tel}直接从指针地址调用这个哈希。
其中一些花括号省略后不影响结果,但是建议规范书写。

多维

多维数组(多维哈希)的本质就是嵌套,但是前面我们提到了perl里数组和哈希表只能存储标量值,所以使用引用和解引用的办法,,把数组(哈希)变成一个标量(指针地址),然后再放入数组(哈希)的值中,从而实现嵌套。

匿名对象

可以构建匿名的对象,这样就没必要去为只用一两次的数组、hash去取名字,有时候取名是很烦的事。

  • 使用中括号[]构建匿名数组
  • 使用大括号{}构建匿名hash
  • 不包含任何元素的[]和{}分别是匿名空数组、匿名空hash
perl -e '
@name=("zhangsan",["lisi","liwu","liliu"]);
print "$name[0]\n";
print "$name[1]\n"; 
print "${$name[1]}[0]\n";  
print "$name[1]->[0]\n"; 
print "$name[1][0]\n";  '

zhangsan
ARRAY(0xf6ca68)
lisi
lisi
lisi

#上面例子中括号里的内容就是匿名数组["lisi","liwu","liliu"]
#匿名数组没有定义名字,直接是个指针地址。
#因为$name[1]是一个指针地址,所以${$name[1]}[0]等价于$name[1]->[0]、$name[1][0]
#其实$name[1][0]是一个不规范的用法。(因为地址应该 解引用 或 使用->)但是再Perl5.0之后的版本已经兼容了这种写法
perl -e '
%hash=("zhangsan"=>{"gender"=>"male","age"=>18},"lisi"=>{"gender"=>"female","age"=>20},"wanger"=>{"gender"=>"male","age"=>25},);
print"$hash{zhangsan}\n";
print"${$hash{zhangsan}}{gender}\n"; 
print"$hash{zhangsan}->{gender}\n"; 
print"$hash{zhangsan}{gender}\n";  '

HASH(0x15ffa68)
male
male
male

#上面例子花括号里的内容就是匿名哈希
#匿名哈希没有定义名字,直接是个指针地址。
#因为$hash{zhangsan}是一个指针地址,所以${$hash{zhangsan}}{gender}等价于$hash{zhangsan}->{gender}、$hash{zhangsan}{gender}。
#其实$hash{zhangsan}{gender}是一个不规范的用法。(因为地址应该 解引用 或 使用->)但是再Perl5.0之后的版本已经兼容了这种写法

使用引用&解引用就可以轻松实现数组嵌套数组、哈希嵌套哈希、哈希嵌套数组、数组嵌套哈希。
匿名对象就被常常使用在嵌套内的数组(哈希)上,因为他是一个被嵌套的数组(哈希),使用起来也常常不需要有名字,直接使用指针地址配合引用&解引用操作即可。

TIPS:使用哈希表和数组时,用$和用->是类似的

对于数组,两个语句等效
$$names[0] = “zhangsan”; ${$names}[0] = “zhangsan”;
$names->[0] = “zhangsan”;


对于哈希,两个语句等效

$$lastnames{“zhangsan”} = “zhangsan”; ${$lastnames}{“zhangsan”} = “zhangsan”;
$lastnames->{“zhangsan”} = “zhangsan“;


因为perl里无论是调用数组还是哈希的内容都是使用$符号,所以${} 和->在很多地方是通用的。
${}理解为”把指针地址解引用“、->理解为”直接从指针地址调用“。
这就是前面提到的”花括号省略后不影响结果“。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注