W Perlu domyślnie kopiowanie struktur referencyjnych (na przykład, tablic tablic lub haszy haszy) odbywa się powierzchownie: kopiowane są tylko same referencje, a nie zagnieżdżone zawartości. Historycznie prowadziło to często do nieoczekiwanych efektów — zmiana wewnętrznej struktury w jednej kopii odbija się w innych. Rozwiązanie: użycie specjalizowanych metod i modułów do głębokiego klonowania, aby stworzyć samodzielną strukturę z niezależnymi elementami zagnieżdżonymi.
Przykład kodu (z użyciem Storable):
use Storable 'dclone'; my $original = { a => [1, 2, { x => 10 }] }; my $copy = dclone($original); $copy->{a}[2]{x} = 20; print $original->{a}[2]{x}; # 10
Kluczowe cechy:
Czy operator “=” ($copy = $ref) działa dla głębokiego kopiowania?
Nie, operator “=” kopiuje tylko samą referencję. Po takim przypisaniu wszelkie zmiany w $copy odbijają się także w $ref.
Czy można użyć funkcji Data::Dumper do głębokiego kopiowania struktury?
Data::Dumper — narzędzie do debugowania i serializacji do łańcucha, nie jest przeznaczone do przywracania struktury danych w pamięci. Do odwrotnego przekształcenia potrzebny jest eval, co jest niebezpieczne i niezalecane z powodów bezpieczeństwa i wydajności.
Czy dclone zawsze działa poprawnie z obiektami (błogosławionymi referencjami)?
Storable::dclone klonuje obiekty, ale tylko wtedy, gdy klasa nie przeciąża metod serializacji lub nie zawiera nietypowych obiektów (na przykład, deskryptorów plików lub silnych referencji do zewnętrznego zasobu). Dla skomplikowanych obiektów należy zaimplementować metody STORABLE_freeze i STORABLE_thaw.
Tablica tablic jest duplikowana operatorem =, w jednej z zagnieżdżonych struktur wprowadzane są zmiany — we wszystkich kopiach widoczne są te same zmiany.
Zalety:
Wady:
Używa się Storable::dclone lub Clone::PP, wszystkie zagnieżdżone struktury są niezależne.
Zalety:
Wady: