除了其他帖子的評論,即使你得到一個獨特的對象標識符,如果你沒有創建一個引用,而不是在哈希鍵以外的地方,該對象可能會超出範圍,收集垃圾,並變得無法訪問。
看看這個代碼示例,它會產生什麼:
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