perl数组硬引用_《中级perl》笔记 - 2, 数组引用 (1)

正式进入主题,perl之所以受欢迎,主要有赖于两大利器: 强大的正则表达式支持 & 强大的复杂数据结构。 复杂数据结构有赖于引用这个重要的实现方式,接下来的几篇笔记将重点讨论列表(也叫数组)引用、哈希引用和函数(也叫子程序)引用。此外还有文件(目录)句柄引用和正则表达式引用,将在后续笔记简略讨论。

引用类似于C语言的指针,它提供间接访问一个(或一组)对象的方法。直接上例子:

my @required = qw(preserver sunscreen warter_bottle jacket);

my @skipper   = qw(blue_shirt hat jacket preserver sunscreen);

for my $item (@required) {

unless (grep $item eq $_, @skipper) {    # 如果$item不在@skipper里

print “skipper is missing $item.\n”;

}

}

这段程序中, @required是Skipper先生需要带的物品,@skipper是他实际带的物品。

for循环判断@required中,@skipper没有的元素,遇到一个打印一个。没有问题,这些代码能很好的工作,我们还可以写出以下代码来检查Gilligan和Professor有什么没带。

my @gilligan = qw(red_shirt hat lucky_socks water_bottle);

for my $item (@required) {

unless (grep $item eq $_, @gilligan) {    # 如果$item不在@gilligan里

print “gilligan is missing $item.\n”;

}

}

my @professor = qw(sunscreen water_bottle silde_rule batteries radio);

for my $item (@required) {

unless (grep $item eq $_, @professor) {    # 如果$item不在@professor里

print “professor is missing $item.\n”;

}

}

看起来也没什么问题,不过你将发现我们重复写类似的代码,解决相同的问题。

sub check_required_items {

my $who = shift;

my @required = qw(preserver sunscreen warter_bottle jacket);

for my $item (@required) {

unless (grep $item eq $_, @_) {

print “$who is missing $item.\n”;

}

}

}

my @gilligan = qw(red_shirt hat lucky_socks water_bottle);

check_required_items (‘gilligan’, @gilligan);

my @skipper = qw(blue_shirt hat jacket preserver sunscreen);

my @professor = qw(sunscreen water_bottle silde_rule batteries radio);

check_required_items(‘skipper’, @skipper);

check_required_items(‘professor’, @professor);

写成函数,我们省去了一部分重复代码。尽管解决了最初的问题,我们还有两个问题需要解决。

•    每次调用函数都需要拷贝整个数组给@_,这是不小的开销,尤其当数组很大时

•    如果我们需要改变原数组,函数调用的方式将无法做到。因为传给函数的@_参数只是原数组的一个拷贝,任何应用在@_上的改变,无法应用到原数组。

引用可以很好地解决这两个问题。

** 对数组进行引用 **

产生一个引用的方法很简单,在被引用的变量前放一个反斜杠 \就产生这个变量的引用。

my $reference_to_skipper = \@skipper;

引用是一个标量,它能使用在任何需要标量的场合 : 函数的标量参数、数组的元素、哈西的键或者值 。。。等等。 像普通标量那样,引用可以进行赋值操作。

my $second_reference_to_skipper = $reference_to_skipper;

my $third_reference_to_skipper = \@skipper;

这三个对@skipper的引用是完全相同的东西,他们都直接指向数组@skipper的内存地址。

** 解析数组引用 **

如何访问被引用的数组? 我们通过解析引用来访问数组元素。访问数组引用,类似于访问普通的数组(@后面的空格是故意加的),区别是要把引用放在大括号里:

@  skipper

@  { $ref_of_skipper }

访问数组中某个元素的方法也类似:

$ skipper [1]

$ {$ref_of_skipper} [1]

于是我们可以改写之前的函数,通过引用来访问数组。

sub check_required_items {

my $who = shift;

my $items = shift;

my @required = qw(preserver sunscreen water_bottle jacket);

for my $item (@required) {

unless (grep $item eq $_, @{$items}) {

print “$who is missing $item.\n”;

}

}

}

我们可以重复调用这个函数,检查人们是否遗失了什么。

my @gilligan = qw(red_shirt hat lucky_socks water_bottle);

check_required_items (‘gilligan’, \@gilligan);

my @skipper = qw(blue_shirt hat jacket preserver sunscreen);

check_required_items(‘skipper’, \@skipper);

my @professor = qw(sunscreen water_bottle silde_rule batteries radio);

check_required_items(‘professor’, \@professor);

函数定义部分,我们只是把@_替换成数组引用;调用函数时,我们把第二参数换成待检查数组的引用。这样做解决了之前的第一个问题,不需要再拷贝原数组给@_,而是函数直接访问目标数组。后面我们将看到引用是如何解决第二个问题的。

我们还可以把函数中的两个shift语句去掉,不过这样维护起来更困难了。

sub check_required_items {

my @required = qw(preserver sunscreen water_bottle jacket);

for my $item (@required) {

unless (grep $item eq $_, @{$_[1]}) {    #$_[1]是传给函数的@_第二个参数

print “$_[0] is missing $item.\n”;    #$_[0]是传给函数的第一个参数

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值