Подтвердить что ты не робот

Копирование hashref в Perl

Возможный дубликат:
Каков наилучший способ сделать глубокую копию структуры данных в Perl?

Я, по-видимому, неправильно понимаю что-то о том, как hashrefs работают в Perl, и я здесь, чтобы исправить это.

Мне нужно получить копию hashref, с которой я могу играть без изменения оригинала. Согласно мои исследования, копирование hashref так же просто, как использование оператора equals:

my $hashref_copy = $hashref;

Но насколько я могу судить, все, что делает, это сделать $hashref_copy указателем на исходный объект. Рассмотрим этот бит игры:


my $hashref = {data => "fish"};

my $hashref_copy = $hashref;
$hashref_copy->{data} = "chips";

print "$hashref->{data}\n";

Если $hashref_copy действительно была независимой копией, я бы ожидал, что этот код напечатает "рыбу". Вместо этого он печатает "чипы".

Итак, либо 1) я что-то недопонимаю или 2) Perl нарушен. Я совершенно уверен, что это не № 2, несмотря на то, что мое эго могло бы подумать.

Где я ошибаюсь? И что мне нужно сделать, чтобы внести изменения в $hashref_copy not в исходном $hashref?

4b9b3361

Ответ 1

Когда вы копируете hashref в другой скаляр, вы копируете ссылку на тот же хеш. Это похоже на копирование одного указателя в другой, но не изменение какой-либо заостренной памяти.

Вы можете легко создать мелкую копию хэша:

my $copy = { %$source };

Бит %$source в контексте списка будет расширяться до списка пар значений ключа. Кудрявые фигурные скобки (анонимный хэш-конструктор) затем берут этот список, а создает из него новый hashref. Неглубокая копия прекрасна, если ваша структура 1-мерная, или если вам не нужно клонировать любую содержащуюся структуру данных.

Чтобы сделать полную глубокую копию, вы можете использовать основной модуль Storable.

use Storable 'dclone';

my $deep_copy = dclone $source;

Ответ 2

Да, назначение просто копирует ссылку (например, копирование значения указателя на другие языки). То, что вы ищете, называется "глубокой копией".

Storable::dclone представляется одним из решений (perldoc Storable для получения дополнительной информации).

Ответ 3

Если это просто хэш и все, что вы ищете, это его копия:

my $hashref = {data => "a"};

my %hash_copy = %{$hashref}; # Create a copy of the hash that $hashref points to
my $hashref_copy = \%hash_copy; # Ref to %hash_copy
$hashref_copy->{data} = "b";

print "$hashref->{data}\n"; # Outputs 'a'
print "$hashref_copy->{data}\n"; # Outputs 'b'