В дополнение к другим комментариям к сообщениям, даже если вы получите уникальный идентификатор объекта, если вы не создадите ссылку на этот объект где-то, кроме как в хеш-ключе, объект может выпасть из области видимости, получить мусорсобраны и становятся недоступными.
Взгляните на этот пример кода и то, что он производит:
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 )