引用
引用一律聲明為標量類型(即$開頭的命名變量),使用\運算符取引用
對引用變量的修改等同於對引用指向實際數據的修改
取標量變量引用:my $scalar_r = \$scalar;
取列表的引用:my $array_r = \@array;
取哈希的引用:my $hash_r = \%hash;
通過引用解決列表無法嵌套的問題:
my @array1 = (10, 20, 30, 40, 50);
my @array2 = ( 1, 2, \@array1, 3, 4);
因為\@array1本質上只是一個標量,所以列表不會被扁平化,依舊保留了嵌套層次
對匿名列表的引用:將列表的()替換為[]:my $array_r = [1, 2, 3, 4, 5];
對匿名哈希的引用:將哈希的()替換為{}:my $hash_r = { apple => "pomme", pear => "poire" };
對引用變量解引用通過{$var_r}實現
列表
my @array = (1, 2, 3, 4, 5);
my $array_r = \@array;
my @array2 = @{$array_r}; #拷貝了數組
哈希與列表類似
對於數組引用,可以將${$ref}簡記為$ref->,例如可以將${$ref}[2]簡記為$ref->[2],而將${${ref}[2]}[1]簡記為$ref->[2]->[1],並進一步簡記為$ref->[2][1]
使用undef銷毀一個引用:undef $ref; perl對於引用指向的數據維護一個引用計數,當計數減到0時引用指向的數據被銷毀,內存空間被釋放
使用引用使得表示復雜的數據結構成為可能。這些數據結構包括矩陣(多維數組)、鏈表、樹、圖等。
一些思考:C/C++的引用主要為了傳地址。與C/C++中的指針、引用不同的是,perl引用除了傳遞地址外,還是perl中將標量(scalar)、列表(list)、哈希(hash)進行一般化(或者說統一)表示的機制,使用引用后,可以將標量、列表、哈希均表示為標量(因為地址本質上是一個無符號整型數,這一點與C中的void*有些類似)。通過引用,就可以解決perl中無法存儲帶有嵌套層次的列表、無法表示復雜數據結構的問題。
Perl引用分為直接引用和符號引用,每種Perl引用都有各自的特點和作用,這里向大家簡單介紹一下Perl直接應用的概念,希望對大家學習有所幫助。
Perl直接引用
1、一般的標量Perl引用
如:
sub add{ my($a,$b)=@_; $$a++; $$b++; }
$a=1; $b=2;
add(\$a,\$b); print "$a,$b\n"; 輸出:2,3。
說明:取變量的Perl引用可以用“\”符號。解Perl引用用“$”符號。
2、數組的Perl引用
數組的Perl引用和標量的Perl引用一樣,在數組名前面加“\”,只是在解Perl引用的時候,使用@符號。如:
@abc=(1,2,3);
$ref=\@abc;
print “@$ref\n”;輸出1,2,3。
print “@$ref[0]\n”;輸出1。
對數組的Perl引用主要用在解決向函數傳遞若干個數組的問題。在Perl中,如果向函數傳遞若干個數組,則他們會將這些數組展開到@_數組中,並不能通過@_這個數組來區分傳遞過來的參數。
如:
sub add{
my(@ref1,@ref2)=@_;
print(“ref1:@ref1\n”);
print(“ref2:@ref2\n”);
}
@a=(1,2,3);
@b=(1,2,3);
@ret=add(@a,@b);
實際輸出的是:ref1:123123
ref2:
可以看到,在子函數add中,並沒有區分傳遞過來的兩個參數。那么如何向函數傳遞多個數組或哈希表呢?
解決的辦法是使用數組Perl引用。如下這個例子說明了如何實現:
sub add{ my @result;
my($ref1,$ref2)=@_;
while( @$ref1 && @$ref2 ){
unshift @result, pop(@{$ref1})+pop(@{$ref2}); }
return @result; }
@a=(1,2,3);
@b=(1,2,3);
@ret=add(\@a,\@b);
print "@ret\n";
輸出:246
3、對哈希表的Perl引用
和數組類似,但是當解Perl引用時要使用$符號,如:
%hash=(abc=>123, def=>456);
$ref=\%hash;
print "%$ref\n";輸出:%HASH(0x83179b4)
print "$$ref{abc}\n";輸出:123
4、表的Perl引用
創建表的Perl引用將會把表中的最后一個值作為產生的標量:
$reflist=\($a,$b,$c);
print $$reflist."\n"; #輸出$c的值。
$reflist=\(1,2...30,40);
print $$reflist."\n"#輸出40
5、創建匿名數組的Perl引用
$arrayreference=[1,2,3]; print $$arrayreference[0]; #輸出1
print $arrayreference->[0]; #輸出1可以用箭頭解Perl引用
當用pop從數組中取值時,數組的第一個元素會被彈出,但是如果用pop用於匿名數組時,可以實現取值而不影響原有數組,如:
@a=(1,2,3);
$s=pop@{[@a]};#perl作為快來計算@{},而快在計算時將創建對匿名數組的Perl引用。
print “@a\n”;#輸出123
當反Perl引用數組Perl引用時,該結果將插入到字符串中,如:想實現輸出uc函數的返回結果:
print "uc(abc)\n"; #輸出uc(abc),並不能將abc轉換成大寫
print "@{[uc(abc)]}\n" #輸出ABC,通過數組Perl引用實現大寫轉換。
可以通過$#$的方式取匿名數組的長度:
$a=[1,2,3,4];
print "$#$a\n";#輸出3,(最后一個元素的下標)
6、創建匿名哈希表的Perl引用
如:
$hashreference={Name=>Sylvster,Gender=>male};
print $hashreference->{"Name"}; #輸出Sylvester,等價於:$$hashreference{Name};
如果需要用each遍歷哈希表,則:
while(($key,$value)=each(%$hashreference)){}
7、用匿名哈希表模仿用戶自定義數據類型
sub Point{
($x,$y)=@_;
return{
x=>$x,
y=>$y
};
}
當使用Point類型時,可以這樣做:
$point=Point(10,20);
print "x:$point->{x},y:$point->{y}\n";
#=========================
創建引用(reference):
solution 1:
$scalarref = \$foo;
$arrayref = \@ARGV;
$hashref = \%ENV;
$coderef = \&handler;
$globref = \*foo;
solution 2:
$scalarref = *foo{SCALAR};
$arrayref = *ARGV{ARRAY};
$hashref = *ENV{HASH};
$coderef = *handler{CODE};
$ioref = *STDIN{IO};
$globref = *foo{GLOB};
$formatref = *foo{FORMAT};
$globname = *foo{NAME}; # "foo"
$pkgname = *foo{PACKAGE}; # "main"
REF:
http://perldoc.perl.org/perlref.html#Making-References
http://www.cnblogs.com/mdyang/archive/2012/05/05/beginning-perl-4-chap-11-13.html