引用 #
一、引用概述 #
引用是指向其他数据的标量值,用于创建复杂数据结构。
1.1 创建引用 #
使用反斜杠 \ 创建引用:
perl
my $scalar = 42;
my $scalar_ref = \$scalar;
my @array = (1, 2, 3);
my $array_ref = \@array;
my %hash = (a => 1, b => 2);
my $hash_ref = \%hash;
my $code_ref = \&some_sub;
1.2 匿名引用 #
匿名数组:
perl
my $array_ref = [1, 2, 3, 4, 5];
匿名哈希:
perl
my $hash_ref = { name => "Tom", age => 25 };
匿名子程序:
perl
my $code_ref = sub {
return "Hello";
};
二、解引用 #
2.1 标量解引用 #
perl
my $value = 42;
my $ref = \$value;
print $$ref;
print ${$ref};
2.2 数组解引用 #
perl
my $arr_ref = [1, 2, 3, 4, 5];
print $arr_ref->[0];
print $arr_ref->[1];
print @$arr_ref;
print @{$arr_ref};
print scalar @$arr_ref;
foreach my $item (@$arr_ref) {
print $item . "\n";
}
2.3 哈希解引用 #
perl
my $hash_ref = { name => "Tom", age => 25 };
print $hash_ref->{name};
print $hash_ref->{age};
my %hash = %$hash_ref;
foreach my $key (keys %$hash_ref) {
print "$key: $hash_ref->{$key}\n";
}
2.4 代码解引用 #
perl
my $code_ref = sub {
my $name = shift;
return "Hello, $name!";
};
print $code_ref->("Tom");
print &$code_ref("Tom");
三、引用类型检查 #
3.1 ref函数 #
perl
my $scalar = 42;
my $arr_ref = [1, 2, 3];
my $hash_ref = { a => 1 };
my $code_ref = sub {};
print ref(\$scalar);
print ref($arr_ref);
print ref($hash_ref);
print ref($code_ref);
print ref(42);
3.2 类型判断 #
perl
sub process {
my $ref = shift;
my $type = ref $ref;
if ($type eq 'ARRAY') {
print "Array with " . scalar(@$ref) . " elements\n";
} elsif ($type eq 'HASH') {
print "Hash with " . scalar(keys %$ref) . " keys\n";
} elsif ($type eq 'CODE') {
print "Code reference\n";
} else {
print "Unknown type: $type\n";
}
}
四、复杂数据结构 #
4.1 数组的数组 #
perl
my $matrix = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
];
print $matrix->[0]->[1];
print $matrix->[0][1];
foreach my $row (@$matrix) {
print "@$row\n";
}
4.2 哈希的数组 #
perl
my $people = [
{ name => "Tom", age => 25 },
{ name => "Jerry", age => 30 },
{ name => "Alice", age => 28 },
];
foreach my $person (@$people) {
print "$person->{name}: $person->{age}\n";
}
4.3 哈希的哈希 #
perl
my $users = {
tom => {
name => "Tom Smith",
email => "tom@example.com",
},
jerry => {
name => "Jerry Brown",
email => "jerry@example.com",
},
};
print $users->{tom}{name};
foreach my $id (keys %$users) {
print "$id: $users->{$id}{name}\n";
}
4.4 混合结构 #
perl
my $config = {
database => {
host => "localhost",
port => 3306,
tables => ["users", "products", "orders"],
},
cache => {
enabled => 1,
servers => ["cache1:11211", "cache2:11211"],
},
};
print $config->{database}{host};
print $config->{database}{tables}[0];
五、引用作为参数 #
5.1 传递数组引用 #
perl
sub process_array {
my $arr_ref = shift;
foreach my $item (@$arr_ref) {
print $item . "\n";
}
}
my @data = (1, 2, 3, 4, 5);
process_array(\@data);
5.2 传递哈希引用 #
perl
sub show_person {
my $person = shift;
print "Name: $person->{name}\n";
print "Age: $person->{age}\n";
}
show_person({ name => "Tom", age => 25 });
5.3 修改参数 #
perl
sub increment {
my $ref = shift;
$$ref++;
}
my $count = 0;
increment(\$count);
increment(\$count);
print $count;
六、引用计数 #
6.1 自动内存管理 #
Perl使用引用计数进行内存管理:
perl
{
my $ref = [1, 2, 3];
}
6.2 循环引用 #
循环引用会导致内存泄漏:
perl
my $a = {};
my $b = {};
$a->{ref} = $b;
$b->{ref} = $a;
6.3 弱引用 #
使用 Scalar::Util 解决循环引用:
perl
use Scalar::Util qw(weaken);
my $a = {};
my $b = {};
$a->{ref} = $b;
$b->{ref} = $a;
weaken $b->{ref};
七、实践练习 #
练习1:树结构 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $tree = {
value => 1,
left => {
value => 2,
left => { value => 4 },
right => { value => 5 },
},
right => {
value => 3,
left => { value => 6 },
right => { value => 7 },
},
};
sub traverse {
my ($node, $depth) = @_;
$depth //= 0;
return unless $node;
my $indent = " " x $depth;
say $indent . $node->{value};
traverse($node->{left}, $depth + 1);
traverse($node->{right}, $depth + 1);
}
traverse($tree);
练习2:JSON数据解析 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
use JSON;
my $json = '{"name":"Tom","age":25,"skills":["Perl","Python"]}';
my $data = decode_json($json);
say "Name: $data->{name}";
say "Age: $data->{age}";
say "Skills: " . join(", ", @{$data->{skills}});
练习3:配置管理 #
perl
#!/usr/bin/perl
use strict;
use warnings;
use v5.10;
my $config = {
app => {
name => "MyApp",
version => "1.0",
},
database => {
connections => [
{ host => "db1.example.com", port => 3306 },
{ host => "db2.example.com", port => 3306 },
],
},
};
say "App: $config->{app}{name} v$config->{app}{version}";
say "Database connections:";
foreach my $conn (@{$config->{database}{connections}}) {
say " $conn->{host}:$conn->{port}";
}
八、总结 #
本章学习了:
- 创建引用(\、[]、{}、sub{})
- 解引用
- 引用类型检查
- 复杂数据结构
- 引用计数
下一章将学习错误处理。
最后更新:2026-03-27