符号引用

    一般来说,类似$$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);