【转载】Perl中的引用

为什么使用引用?

在perl4中,hash表中的value字段只能是scalar,而不能是list,这对于有些情况是很不方便的,比如有下面的数据:

Chicago, USA
Frankfurt, Germany
Berlin, Germany
Washington, USA
Helsinki, Finland
New York, USA

我们想要按国家将城市分类,每个国家后面对应城市列表,如果用perl4来做,必须将城市列表组合成字符串才行,如果用perl5就可以用引用来做,有了引用,就可以构造复杂的hash结构,就可以用列表作为hash的值了。

如何定义引用

方法一 使用斜线\

定义变量的时候,在变量名前面加个\,就得到了这个变量的一个引用,比如

# 数组的引用my@array= (1,2,3) ;my$aref=\@array ;

#哈希的引用my%hash= ("name"=>"zdd","age"=>30,"gender"=>"male") ;my$href=\%hash ;

#标量的引用my$scalar=1 ;my$sref=\$scalar ;

方法二 匿名引用

方法一不是很常用,最常用的还是匿名引用,方法如下

匿名数组引用-用[]定义

$aref= [ 1,"foo",undef,13 ];

匿名数组的元素仍然可以是匿名数组,所以我们可以用这种方法构造数组的数组,可以构造任意维度的数组。

my $aref = [        [1, 2, 3],        [4, 5, 6],        [7, 8, 9],]

匿名哈希引用-用{}定义

$href= { APR =>4, AUG =>8 };

使用引用

定义了引用之后,可以使用不同的方法来访问引用,这里主要有三种方法。记忆这三种方法有个诀窍,将他们与普通的变量访问作比较即可。

方法一

与普通变量的访问方法相比,假设原来的变量名是name,则此方法在所有name出现的地方用$name代替,如下

my $scalar = 1 ;my @array = (1, 2, 3) ;my %hash = (‘zdd‘ => 30, ‘autumn‘ => 27) ;

my $sref = \$scalar ;   # scalar referencemy $aref = \@array ;    # array referencemy $href = \%hash ;     # hash reference

# 方法一print $$sref, "\n" ;  # 用$sref代替srefprint @$aref, "\n" ;   # 用$aref代替aref print %$href, "\n" ;   # 用$href代替hrefprint $$aref[2], "\n" ;print $$href{‘zdd‘}, "\n" ;

方法二

与普通变量的访问方法相比,假设变量原来的名字是name,则现在用{$name}来代替name。

@a        @{$aref}         An array   reverse@a  reverse @{$aref}    Reverse the array   $a[3]      ${$aref}[3]       An element of the array   $a[3] =17;   ${$aref}[3] =17    Assigning an element

同理,哈希引用的使用方法如下。

%h          %{$href}           A hash   keys%h      keys%{$href}        Get the keys from the hash   $h{‘red‘}      ${$href}{‘red‘}       An element of the hash   $h{‘red‘} =17   ${$href}{‘red‘} =17    Assigning an element

注意:当{}内部是$var的形式时,{}是可以省略的,也就是说@{$aref}等价于@$aref,不过初学最好养成使用{}的习惯。

方法三

前两种方法比较繁琐,这种很简洁,就是使用箭头符号->

$aref->[]  数组解引用

$href->{}  哈希解引用

$href->()  子过程解引用

$aref->[0] =3 ; $href->{name} ="autumn" ; $sref=2 ;

也可以将引用赋值给其他变量

my$aref1=$aref ;my$href1=$href ;my$scalar1=$scalar ;

解引用总结

my $scalar = 1 ;my @array = (1, 2, 3) ;my %hash = (‘zdd‘ => 30, ‘autumn‘ => 27) ;

my $sref = \$scalar ;   # scalar referencemy $aref = \@array ;    # array referencemy $href = \%hash ;     # hash reference

# 方法一print $$sref, "\n" ;print @$aref, "\n" ;print %$href, "\n" ;print $$aref[2], "\n" ;print $$href{‘zdd‘}, "\n" ;

# 方法二print ${$sref}, "\n" ;print @{$aref}, "\n" ;print %{$href}, "\n" ;print ${$aref}[2], "\n" ;print ${$href}{‘zdd‘}, "\n" ;

# 方法三,不适用于标量print $aref->[0], "\n" ;print $href->{‘zdd‘}, "\n" ;

数组的数组

@a = (    [1, 2, 3],    [4, 5, 6],    [7, 8, 9])

我们知道[1, 2, 3]定义了一个(1, 2, 3)的匿名引用,所以数组a实际上包含三个元素,每个元素是一个引用,该引用指向一个数组,所以我们可以用下面的方法来访问数组元素(注意,下标从0开始)

$a[1][2]表示第二行第三列元素6,也可以写成$a[1]->[2],不过很少有人这么写。还可以写成${$a[1]}[2],几乎没人这么写!

多维数组的另一个写法如下:

my $aref = [1, [2, 3], [4, 5, 6]] ;print $aref->[0] , "\n" ; #1print $aref->[1][1], "\n" ; #3print $aref->[2][0], "\n" ; #4

这两者的区别有以下几点:

  • 前者是真正的数组,所以定义变量是使用@,后者是指向匿名数组的引用,所以定义的时候使用$
  • 前者的数组元素是匿名数组,而外层数组则是实体数组,后者无论元素还是外层数组都是匿名数组
  • 前者可以用$a[x][y]的形式访问,而后者只能用解引用的方式访问,即$a->[x][y]的形式。

数组的哈希

哈希的数组

哈希的哈希

也就是哈希表中的每个元素也是一个哈希表,比如一个学生集合组成的哈希,其key是学生名字(唯一),其值是每个学生的属性,比如年龄,身高及学号等。

my $student_properties_of = {    ‘zdd‘ => {        ‘age‘ => 30,        ‘hight‘ => 170,        ‘id‘ => ‘001‘,    },

    ‘autumn‘ => {        ‘age‘ => 27,        ‘hight‘ => 165,        ‘id‘ => ‘002‘,    }} ;

引用的赋值

$aref2 = $aref1; 将使得$aref2和$aref1指向同一个数组,如果想将$aref1指向的数组拷贝一份给$aref2的话,使用下面的方法,[]里面对数组进行解引用,而[]以解引用后的数组为内容生成了一个新的匿名数组,又赋值给$aref2。

$aref2 = [@{$aref1}]; 

注意:不能使用下面的形式,外层的[]是不可缺少的。由于=左边是标量,所以右边的数组会被解释为标量环境,得到的是数组元素个数,而不是元素本身。但是如果加上[]就可以了,这样perl知道这是一个匿名数组的赋值。

$aref2 = @{$aref1};

判断一个变量是否是引用

使用ref函数即可,如果变量是引用则返回真,否则返回假。实际上它更智能,它会返回引用对应的类型,比如HASH或者ARRAY。

my $aref1 = [1, 2, 0] ;

print ref $aref1, "\n" ; #输出 ARRAY

if (ref $aref1) {    print "true\n" ; #输出 true}

判断两个引用是否指向同一个目标

可以用eq,这将以字符串的形式判断,也可以使用==

my $aref1 = [1, 2, 0] ;my $aref2 = $aref1 ;print $aref1, "\n" ;print $aref2, "\n" ;

if ($aref1 eq $aref2) {    print "reference equal\n" ;}if($aref1 == $aref2) {    print "reference equal\n" ;}

产生如下输出

ARRAY(0x248bec)
ARRAY(0x248bec)
reference equal (eq)
reference equal (==)

时间: 2024-10-12 21:00:18

【转载】Perl中的引用的相关文章

[Perl系列—] 2. Perl 中的引用用法

Perl 中的引用,为什么要使用引用? 对于熟悉C语言的开发者来说, 指针这个概念一定不陌生. Perl 的引用就是指针,可以指向变量.数组.哈希表甚至子程序. Perl5中的两种Perl引用类型为硬Perl引用和符号Perl引用.符号Perl引用含有变量的名字,它对运行时创建变量名并定位很有用,基本上,符号Perl引用就象文件名或UNIX系统中的软链接.而硬Perl引用则象文件系统中的硬链接. Perl4只允许符号Perl引用,给使用造成一些困难.例如,只允许通过名字对包的符号名哈希表(名为_

perl 中的引用

perl 语言中的引用共分为两类: 声明引用时只需要在对象的前面加上反斜杠 第一列是数组的引用: 代码示例: my @array = (1, 2, 3); my $array_ref = \@array; 第二种是哈希的引用 代码示例: my %hash = (1, 2, 3, 4); my $hash_ref = \@hash; 通过引用去访问对应的值,通过 -> 操作符 数组的引用, 通过 [ ] 中括号 加上对应的下标,代码示例: my @array = (1, 2, 3); my $ar

(转载)理解Java中的引用传递和值传递

关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题,有论坛说Java中只有值传递,也有些地方说引用传递和值传递都存在,比较容易让人迷惑.关于值传递和引用传递其实需要分情况看待,今天学习和分析一下,着急可以先看最后的结论. 1.基本类型和引用类型在内存中的保存 Java中数据类型分为两大类,基本类型和对象类型.相应的,变量也有两种类型:基本类型和引用类型.基本类型的变量保存原始值,即它代表的值就是数值本身:而引用类型的变量保存引用值,"引用值"指向内存空间的地址,代表了某

【转载】Perl中字符串编码的处理

在 Perl看来, 字符串只有两种形式. 一种是octets, 即8位序列, 也就是我们通常说的字节数组. 另一种utf8编码的字符串, perl管它叫string. 也就是说: Perl只熟悉两种编码: Ascii(octets)和utf8(string). utf8 flag在perl内部, 字符串结构由两部分组成: 数据和utf8 flag. 比如字符串"中国"在perl内部的存储是这样:utf8 flag 数据On 中国假如utf8 flag是On的话, perl就会把中国当成

请注意,java中没有引用传递-----转载

1 说明:本文的适用对象为java初学者.如果有读者发现文章中有叙述不妥之处,请指正. 2 3 今天在论坛上有人提了一个关于java中调用函数时有没有引用传递的问题,可谓是吵的不可开交.有人说java只有值传递,也有人说java既有值传递也有引用传递,那么java中到底有没有引用传递呢,下面我来分析一下. 4 5 一.首先来明确一下"值传递"和"引用传递的"区别 6 7 值传递:是对所传递参数进行一次副本拷贝,对参数的修改只是对副本的修改,函数调用结束,副本丢弃,原

Perl中的真与假

Perl认为真值是自明的(self-evident), 表示任何事物的真值都可以计算.Perl以实用的方式来定义真值,即一个实体的真值取决于这个实体的类型.Perl总是乐观的认为:这个世界上真的东西远比假的东西多的多. Perl区别与任何其他计算机语言,Perl是语言学家创造的,而语言的意思离不开上下文语境,所以Perl中的真值都可以在标量(标量$与数组@类似于英文中的单数与复数, book 与 books的区别, 真值在现实世界中,应该就是单数,所以是标量)计算,除此之外,不会做任何类型的强制

Java中的引用和指针

java中内存的分配方式有两种,一种是在堆中分配,一种是在堆栈中分配,所有new出来的对象都是在堆中分配的,函数中参数的传递是在栈中分配的.通常情况下堆的内存可以很大,比如32位操作系统中的虚拟内存都可以被堆所使用(当内存紧张的时候甚至硬盘都可以是堆的存储空间),而堆栈的内存分配是有限的. 这和c++中内存分配差不多.java中有几种基本类型如int,float,double,char,byte等,他们不是对象,除此之外一切都是对象,所有的对象都是在堆上分配的.但好像在C#中这些都有封装好的一些

Perl中Schwartzian转换问题

Perl中著名的Schwartzian转换,其产生背景主要涉及到排序问题: 比如说,根据文件名以字母顺序排序,代码如下: use strict; use warnings; my @files = glob "*.xml"; #perl中文件操作符glob提供相当于shell中的通配符的功能 my @sorted_files = sort @files; #sort(),排序,默认是字母顺序排序 比如说,根据文件名长度排序,其代码如下: use strict; use warnings

无法解析的外部符号 _ ,该符号在函数 " __main中被引用 && This function or variable may be unsafe.

加上winsock2的运行库看看吧,一般不用加的啊 #pragma comment(lib,"Ws2_32.lib") 应该就没有问题了吧^_^ 以下为转载 http://blog.chinaunix.net/uid-20672257-id-2955771.html 1.将过去的工程用VS2010打开的时候.你有可能会遇到一大堆的警告:warning C4996. 比如:warning C4996: 'sprintf': This function or variable may be