引用 #

一、引用概述 #

引用是指向其他数据的标量值,用于创建复杂数据结构。

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