Programmingバックエンド開発者

Perlにおける複雑なデータ構造の浅いコピーと深いコピーの違いを説明してください。コピー間の不要なリンクを防ぐためにはどうすればいいですか?

Hintsage AIアシスタントで面接を突破

回答

Perlでは、複雑なデータ構造(たとえば、配列の配列、ハッシュのハッシュ)をコピーする際に、「浅いコピー」(shallow copy)と「深いコピー」(deep copy)の違いを理解することが重要です。

浅いコピーは新しいコンテナ(たとえば、配列やハッシュ)を作成しますが、その中の要素は元のオブジェクトと同じオブジェクトを参照します。これにより、予期しない挙動が生じる可能性があります — コピー内のデータを変更すると元のデータにも影響を与えます。

深いコピーは、すべてのネストされた要素を再帰的にコピーして、完全に独立した構造を作成します。Perlで深いコピーを行うためには、よく Storable または [Clone] モジュールが使用されます:

use Storable 'dclone'; my $original = { a => [1, 2, { b => 3 }] }; my $copy = $original; # 浅いコピー my $deep = dclone($original); # 深いコピー $copy->{a}[2]{b} = 42; # 両方に影響を与えます $copy と $original! $deep->{a}[2]{b} = 99; # $deep のみ変更

深いコピーは、構造が完全に独立していることを保証します。

トリックの質問

変数への代入による配列のコピーと参照による配列のコピーの違いは何ですか?ひとつを変更してももうひとつに影響を与えないように配列を正しくコピーするにはどうすればいいですか?

しばしば、単に参照を代入すれば良いと答えます: $copy = \@arr; — しかしこれは誤りです。両方の変数が同じ配列を指してしまうからです。独立したコピーを行うには、次のようにします:

my @copy = @original; # これで配列は独立しています

ネストされた構造をコピーする必要がある場合は、Storable::dcloneを通じて深いコピーが必要です。

テーマのバイアスによる実際の誤りの例


ストーリー

大きなXMLファイルを解析するプロジェクトで、各ドキュメントに対してテンプレートハッシュをコピーしました。ドキュメントの一つでの変更が他のドキュメントに影響を与え、「消えた」または「ずれた」データに関する謎のバグが発生しました。

ストーリー

セッションを保存するためにユーザーのハッシュの配列を使用しました。新しいユーザーリストのために配列を再作成する際、参照のみをコピーしたため前のセッションのユーザーデータが「漏れ」ました。

ストーリー

大量配信のためのEメールテンプレートを実装する際、ネストされたオブジェクトを含む元の構造を代入でコピーしました。テンプレートのテキストに対する変更が配信の間で「漏出」し、受取人に古いメッセージが送信されました。