除了其他帖子的评论,即使你得到一个独特的对象标识符,如果你没有创建一个引用,而不是在哈希键以外的地方,该对象可能会超出范围,收集垃圾,并变得无法访问。
看看这个代码示例,它会产生什么:
use strict;
use warnings;
$|++;
{
package X;
use Moose;
has side => (isa => 'Str', is => 'rw', required => 1);
has foo => (isa => 'Int', is => 'rw', required => 1);
sub DEMOLISH {
my ($self) = @_ ;
printf "Destroyed %i (%s)\n" , $self->foo, $self->side;
}
__PACKAGE__->meta->make_immutable;
}
{
package Y;
my $hash = {};
for (1 .. 5){
print "Creating $_ \n";
my $k = X->new(foo => $_ , side => 'key');
my $v = X->new(foo => $_, side => 'value');
$hash->{$k} = $v;
print "Created $_ at $k \n";
}
for (keys %$hash){
print "Emptying Hash slowly, doing key $_ \n";
delete $hash->{$_};
}
}
输出:
Creating 1
Created 1 at X=HASH(0x2597d08)
Destroyed 1 (key)
Creating 2
Created 2 at X=HASH(0x2fca7c0)
Destroyed 2 (key)
Creating 3
Created 3 at X=HASH(0x2fca808)
Destroyed 3 (key)
Creating 4
Destroyed 1 (value)
Created 4 at X=HASH(0x2597d08)
Destroyed 4 (key)
Creating 5
Created 5 at X=HASH(0x2597d68)
Destroyed 5 (key)
Emptying Hash slowly, doing key X=HASH(0x2597d68)
Destroyed 5 (value)
Emptying Hash slowly, doing key X=HASH(0x2597d08)
Destroyed 4 (value)
Emptying Hash slowly, doing key X=HASH(0x2fca808)
Destroyed 3 (value)
Emptying Hash slowly, doing key X=HASH(0x2fca7c0)
Destroyed 2 (value)
你会看到每一个关键对象拿到的结束GC'd因为那里没有任何提及它的循环。 你会看到一个额外的有趣的事情,我们为“4”生成的关键对象使用与“1”相同的内存地址,所以当我们在哈希中替换它的值时,该值也是GC'd。 :/
解决这个问题相当简单,这里是做这件事:
use strict;
use warnings;
$|++;
{
package X;
use Moose;
use Data::UUID;
my $ug = Data::UUID->new();
has side => (isa => 'Str', is => 'rw', required => 1);
has foo => (isa => 'Int', is => 'rw', required => 1);
has uuid => (isa => 'Str', is => 'rw', required => 1 , builder => '_build_uuid');
sub _build_uuid {
return $ug->create_str();
}
sub DEMOLISH {
my ($self) = @_ ;
printf "Destroyed %i (%s , %s)\n" , $self->foo, $self->side, $self->uuid;
}
__PACKAGE__->meta->make_immutable;
}
{
package Y;
my $hash = {};
my $keys = {};
for (1 .. 5){
print "Creating $_ \n";
my $k = X->new(foo => $_ , side => 'key');
my $v = X->new(foo => $_, side => 'value');
$keys->{$k->uuid} = $k;
$hash->{$k->uuid} = $v;
print "Created $_ at $k \n";
}
for (sort keys %$hash){
print "Emptying Hash slowly, doing key $_ \n";
delete $hash->{$_};
delete $keys->{$_};
}
}
输出:
Creating 1
Created 1 at X=HASH(0x2a12b58)
Creating 2
Created 2 at X=HASH(0x2a0d068)
Creating 3
Created 3 at X=HASH(0x2a28960)
Creating 4
Created 4 at X=HASH(0x2a28b28)
Creating 5
Created 5 at X=HASH(0x2a28c18)
Emptying Hash slowly, doing key ADD9C702-E254-11DF-A4A3-F48B02F52B7F
Destroyed 1 (value , ADD9CA18-E254-11DF-A4A3-F48B02F52B7F)
Destroyed 1 (key , ADD9C702-E254-11DF-A4A3-F48B02F52B7F)
Emptying Hash slowly, doing key ADD9CBD0-E254-11DF-A4A3-F48B02F52B7F
Destroyed 2 (value , ADD9CCD4-E254-11DF-A4A3-F48B02F52B7F)
Destroyed 2 (key , ADD9CBD0-E254-11DF-A4A3-F48B02F52B7F)
Emptying Hash slowly, doing key ADD9CE5A-E254-11DF-A4A3-F48B02F52B7F
Destroyed 3 (value , ADD9CF5E-E254-11DF-A4A3-F48B02F52B7F)
Destroyed 3 (key , ADD9CE5A-E254-11DF-A4A3-F48B02F52B7F)
Emptying Hash slowly, doing key ADD9D0DA-E254-11DF-A4A3-F48B02F52B7F
Destroyed 4 (value , ADD9D1DE-E254-11DF-A4A3-F48B02F52B7F)
Destroyed 4 (key , ADD9D0DA-E254-11DF-A4A3-F48B02F52B7F)
Emptying Hash slowly, doing key ADD9D38C-E254-11DF-A4A3-F48B02F52B7F
Destroyed 5 (value , ADD9D49A-E254-11DF-A4A3-F48B02F52B7F)
Destroyed 5 (key , ADD9D38C-E254-11DF-A4A3-F48B02F52B7F)
感谢的是,蒂洛 – Klaus 2010-10-28 04:50:42
正确的方式来获得一个参考的唯一标识符是使用标量::的Util :: refaddr http://search.cpan.org/~gbarr/Scalar-List- Utils/lib/Scalar/Util.pm – friedo 2010-10-28 04:55:30