1. 程式人生 > >Perl的淺拷貝和深度拷貝

Perl的淺拷貝和深度拷貝

-i hal 層次 sha 復雜 實現 圖片 概念 階段

首先是深、淺拷貝的概念:

  • 淺拷貝:shallow copy,只拷貝第一層的數據。Perl中賦值操作就是淺拷貝
  • 深拷貝:deep copy,遞歸拷貝所有層次的數據,Perl中Clone模塊的clone方法,以及Storable的dclone()函數是深拷貝

所謂第一層次,指的是出現嵌套的復雜數據結構時,那些引用指向的數據對象屬於深一層次的數據。例如:

@Person1=('wugui','tuner');
@Person2=('longshuai','xiaofang',['wugui','tuner']);
@Person3=('longshuai','xiaofang',\@Person1);

@Person1只有一層深度,@Person2@Person3都有兩層深度。

當進行賦值時,拷貝給目標的只是第一層數據對象。

@Person1_shallow=@Person1;
@Person2_shallow=@Person2;
@Person3_shallow=@Person3;

拷貝給@Person1_shallow的是整個@Person1數據,它們在結果上完全等價,拷貝給@Person{2,3}_shallow的是@Person{2,3}的第一層數據,也就是兩個元素和一個引用,拷貝引用時不會對引用進行遞歸拷貝給賦值對象。簡單地說,淺拷貝的過程就是源數據是怎樣的,拷貝後就是怎樣的。

如下圖:

技術分享圖片

因為淺拷貝時引用不會進行遞歸,所以拷貝前後的兩個對象都指向同一個引用。所以修改它們共同引用的數據,同時也會修改另一份數據。例如:

@Person=('longshuai','xiaofang',['wugui','tuner']);
@Person_shallow=@Person;

$Person_shallow[2][1]="fairy";

say "$Person_shallow[2][1]";   # 輸出:fairy
say "$Person[2][1]";           # 輸出:fairy

上述例子中只是給@Person_shallow進行了元素修改操作,但同時卻把原始數據@Person也改了。因為@Person_shallow@Person引用的數據對象是相同的。

為了在拷貝階段保護引用的數據對象,Perl提供了深拷貝的方式。它會對引用進行遞歸,拷貝引用所指向的數據對象。如圖:

技術分享圖片

也就是說,深拷貝的方式使得拷貝前後出現了兩個完全獨立的、互不影響的數據對象,修改其中任何一個對象都不會影響另一個。

Perl提供了一個Clone包(現在包的概念就是模塊),它的clone()可以遞歸拷貝,也就是深拷貝。Storable模塊也提供了dclone()函數進行深拷貝。在拷貝層次低於或等於3層時,Clone()的拷貝速度更快,在層次大於或等於4層時,dclone()速度更快。

需要註意,clone()和dclone()的參數都必須是引用變量,當然,也可以是\構建的引用。

例如,使用Clone的clone()方法進行深拷貝:

shell> cpan -i Clone
use 5.010;
use Clone qw(clone);

@Person=('longshuai','xiaofang',['wugui','tuner']);
$Person_deep=clone(\@Person);

$Person[2][1]="fairy";

say "$Person[2][1]";         # 輸出:fairy
say "$Person_deep->[2][1]";  # 輸出:tuner

同樣,使用Storable模塊的dclone()。

use 5.010;
use Storable qw(dclone);

@Person=('longshuai','xiaofang',['wugui','tuner']);
$Person_deep=dclone(\@Person);

$Person[2][1]="fairy";

say "$Person[2][1]";         # 輸出:fairy
say "$Person_deep->[2][1]";  # 輸出:tuner

關於Storable模塊,他是用來實現數據持久化的主要工具,後面會有專門的文章詳細介紹。

Perl的淺拷貝和深度拷貝