Perl符号引用和强引用

本文深入探讨Perl中的符号引用机制,解释如何在代码中使用符号引用来访问全局变量,以及其对数组和散列表的适用性。同时,文章详细介绍了硬引用的概念,包括如何创建、使用以及在代码中传递硬引用的方法。最后,文章强调了严格模式的作用,以及如何通过关闭此模式来避免潜在的错误。

符号引用

    一般来说,类似$$var的结构表示,$var是一个引用变量,而且程序员希望该表达式能够返回$var所指向的值。
假如$var不是引用变量的话会出现什么情况呢?Perl并不是断然打印出错误信息,而是尝试检查$var的值是否为一字符串。如果是,Perl将以该字符串作为正规的变量名与这个变量重新加以组合!考虑下面的例子:
#!/usr/bin/perl
$x=10;
$var="x";
$$var=30;
print $x."\n";
print $$var."\n";
print "$$var\n";
${$var}=25;
print "${$var}"."\n";
 
    当对$$var进行间接访问时,Perl首先检查$var是否是引用,在这里它不是,而是字符串。于是Perl会再给该表达式一次机会:它将$var的内容当作变量标识符($x)。这样一来,最终$x的值就被修改成30了。
    应当注意重要的一点是符号引用只对全局变量有效,而不能应用于那些用my标识为私有的变量。
 
符号引用对数组和散列表同样适用:
$var = "x";
@$var = (1,2,3); #将@x的值设置为右边的枚举列表
     注意$var前面的符号指示变量的存取类型:$$var等价于$x,@$var也等价于@x,这种特性非常有用。
     对于那些在Perl的早期版本中就实现过此类功能的人来说,这要比使用eval更为高效。举例说明,你要在自己的脚本程序中,处理诸如“-Ddebug_level=3”的选项,并设置$debug_level变量。下面是其中的一种实现方式:
while($arg = shift @ARGV){
if($arg =~ /-D(\w+)=(\w+)/){
$var_name = $1; $value = $2;
$$var_name = $value; #更为简洁的可书写为:$$1 = $2;
}
}
     从另一方面说,Perl竭尽全力使一个表达式正常工作,有时却于事无补。在前面的例子中,如果你所希望程序使用一个真正的引用,而不是字符串的话,那么你就会希望Perl能够指出这种情况而不是做任何的假定。幸运的的是,这种“急于求成”的方式可以被关闭。
     Perl有许多编译时指令和指示。strict编译指示将告诉Perl做严格的错误检查。你甚至科以指定需要进行严格检查的范围,其中之一就包括“refs”这一项:
        use strict 'refs';    #告诉Perl不允许符号引用
        $var = "x";
        $$var = 30;
无论何时你试图使用符号引用时均会导致运行时错误:
can't use string ("x") as a SCALAR ref while "strict refs" in use at try.pl line 3
strict指令直至程序块结束仍然有效。可以通过输入no strict 或更明确的no strict 'refs'将其关闭。
 
硬引用
1. 另一种数据类型的地址。硬引用本身是标量值。
$ptr=\任何其他类型:$,@,%,&,*(typeglob),$(another ptr)
引用本身是SCALAR保存的是指针值,引用的内容是$$ptr, %$ptr, @$ptr等等。
 
2. 创建对变量的引用(指针)时没有必要命名,如果变量或者子程序没有名称则成为匿名变量或匿名子程序。中缀运算符->用于分离匿名数字和匿名散列的引用(非必须,但是增加程序可读性)。
匿名数字元素包含在放括号[]中,方括号表达式不同与下标表达式,用于给标量赋值的情况。注意“”中[]为字面量。例如
my $arrayref = ['luffy', 'nami', 'robin'];
print $arrayref->[1].”\n”;
print $$arrayref[1].”\n”;
print ${$arrayref}[1].”\n”; #这三种形式相同
print “@{$arrayref}\n” #整个数组
#匿名哈希通过{}判断,同样这里与散列下标的花括号不同,它用于将散列赋值给标量引用。
my $hashref = {Captain=”luffy”, Helmsman=”nami”, Historian=”robin”}
print “$hashref->{Captain}\n”;
print keys %$hashref, “\n”;
 对于各类嵌套数据结构的使用(等同于匿名数组/哈希)同样可以使用$array->[3]->[3],${$array->[3]}[3], 或者$array->[3][3]; 而@{$array->[3]}表示整个嵌套数字,%{$array->[2]}表示真个嵌套哈希。内嵌套哈希的哈希可以用$hashref->{Captain}->{Luffy}或者直接$$hashref{Captain}{Luffy}。
#!/usr/bin/perl
 
my $hashref={Captain=>"luffy", Helmsman=>"nami", Historian=>"robin"};
my $arrayref = [1, 2, $hashref]; #注意这里不能是%$hashref .
#print print $arrayref->[2]; #类型是HASH(地址);
print $arrayref->[2]->{Captain};
 
3. 匿名子程序
my $subref=sub{print @_;};
&$subref('a','b','c');
子程序传递引用:以往传递子程序时,都复制到@_数组中。如果变量太大会造成@_太大,需要放回的结果也太大。因此传递变量最有效和最简单的方式就是通过地址引用(依然通过@_传递地址,和C差不多)。
sub gifts{
 my($n, $a) = @_; #将引用本地化
 print “There are $$n gifts”;
 print “@$t\n”;
 push(@$t, 'abcd');
}
gifts(\$num, \@toys); #然后abcd被实际插入到了@toys中。
 
4. 文件句柄引用
open(LOG, “/etc/passwd”) || die “error while opening”;
&readit(\*LOG)
sub readit{
my($mylog)=@_;
while(<$mylog>) {
print;
}
close $mylog; #这里关闭,外面就不可以使用这个文件句柄了!
}
 
5. ref函数:用于测试引用存在,如果参数是引用则返回真。如果在printf “%s”还可以显示引用的类型。
$ptr = \@arr;
printf(“\$ptr is a reference to %s”, ref($ptr)) if ref($ptr);

### Perl 引用的介绍 Perl 引用是一种非常有用的数据类型,它可以让用户将数据结构或者代码片段作为一个整体进行处理。引用允许在变量中存储对其他变量的引用,是 Perl 中一种重要的数据类型,常见用途包括处理数组、哈希等复杂数据结构,以及引用函数等[^1][^3]。 ### Perl 引用的使用方法 #### 创建引用Perl 中,可以使用反斜杠(`\`)运算符来创建对变量的引用。例如创建一个对数组的引用: ```perl my @array = (1, 2, 3); my $array_ref = \@array; ``` 这里 `$array_ref` 就是对数组 `@array` 的引用[^3]。 #### 解引用引用是获取引用所指向的值的操作。对于数组引用,使用 `@` 符号进行解引用;对于哈希引用,使用 `%` 符号进行解引用。示例如下: ```perl my @array = (1, 2, 3); my $array_ref = \@array; my @deref_array = @$array_ref; ``` 这里 `@deref_array` 就是通过解引用 `$array_ref` 得到的数组。 #### 引用函数 创建函数的引用可以使用 `\&` 符号,调用引用函数的格式是 `&` 加上创建的引用名。示例如下: ```perl #!/usr/bin/perl # 函数定义 sub PrintHash{ my (%hash) = @_; foreach $item (%hash){ print "元素 : $item\n"; } } %hash = ('name' => 'it', 'age' => 3); # 创建函数的引用 $cref = \&PrintHash; # 使用引用调用函数 &$cref(%hash); ``` ### 示例总结 以下是一个综合示例,展示了数组引用、哈希引用函数引用的使用: ```perl #!/usr/bin/perl # 数组引用示例 my @numbers = (1, 2, 3, 4, 5); my $numbers_ref = \@numbers; print "数组引用引用结果: @$numbers_ref\n"; # 哈希引用示例 my %person = ('name' => 'John', 'age' => 30); my $person_ref = \%person; print "哈希引用引用结果: $person_ref->{name}, $person_ref->{age}\n"; # 函数引用示例 sub greet { my $name = shift; print "Hello, $name!\n"; } my $greet_ref = \&greet; &$greet_ref("Alice"); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值