En plus des autres commentaires posts, même si vous obtenez un identificateur d'objet unique, si vous ne créez pas de référence à cet objet ailleurs que dans la clé de hachage, l'objet peut tomber hors de portée, récupérer les ordures et devenir inaccessible.
Jetez un oeil à cet exemple de code et ce qu'il produit:
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->{$_};
}
}
Sorties:
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)
Vous verrez que chaque objet clé obtenu GC'd à la fin de la boucle en raison de ne plus y faire référence. Et vous verrez une chose amusante supplémentaire, que l'objet-clé que nous avons généré pour "4" utilise la même adresse mémoire que "1", donc lorsque nous avons remplacé sa valeur dans le hachage, la valeur était aussi GC'd. :/
La résolution de ce problème est assez simple, et voici une façon de le faire:
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->{$_};
}
}
Sortie:
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)
Merci pour cela, Thilo – Klaus
La bonne façon d'obtenir l'identifiant unique d'une référence est d'utiliser Scalar :: Util :: RefAddr http://search.cpan.org/~gbarr/Scalar-List- Utils/lib/Scalar/Util.pm – friedo