Perl的浅拷贝和深度拷贝

首先是深、浅拷贝的概念:

  • 浅拷贝: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都有两层深度。

当进行赋值时,拷贝给目标的只是第一层数据对象。

@[email protected];
@[email protected];
@[email protected];

拷贝给@Person1_shallow的是整个@Person1数据,它们在结果上完全等价,拷贝给@Person{2,3}_shallow的是@Person{2,3}的第一层数据,也就是两个元素和一个引用,拷贝引用时不会对引用进行递归拷贝给赋值对象。简单地说,浅拷贝的过程就是源数据是怎样的,拷贝后就是怎样的。

如下图:

因为浅拷贝时引用不会进行递归,所以拷贝前后的两个对象都指向同一个引用。所以修改它们共同引用的数据,同时也会修改另一份数据。例如:

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

$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模块,他是用来实现数据持久化的主要工具,后面会有专门的文章详细介绍。

原文地址:https://www.cnblogs.com/f-ck-need-u/p/9721265.html

时间: 2024-08-05 08:23:23

Perl的浅拷贝和深度拷贝的相关文章

Python 直接赋值、浅拷贝和深度拷贝区别

Python 直接赋值.浅拷贝和深度拷贝区别 转自https://www.runoob.com/w3cnote/python-understanding-dict-copy-shallow-or-deep.html 直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 解析 1.b = a: 赋值引用,a 和 b 都指向同一个对象. # -*- c

Python 直接赋值、浅拷贝和深度拷贝解析

直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 字典浅拷贝实例 实例 >>> a = {1: [1,2,3]} >>> b = a.copy() >>> a, b ({1: [1, 2, 3]}, {1: [1, 2, 3]}) >>> a[1].append(4) >>

Python 直接赋值、浅拷贝和深度拷贝全解析

直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象. 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象. 字典浅拷贝实例 实例 1 2 3 4 5 6 7 >>>a = {1: [1,2,3]} >>> b = a.copy() >>> a, b ({1: [1, 2, 3]}, {1: [1, 2, 3]}) >>> a[1].appe

学习python--第八天(直接赋值、浅拷贝和深度拷贝解析)

直接赋值:其实就是对象的引用(别名). 浅拷贝(copy):拷贝父对象,不会拷贝对象的内部的子对象.--只拷贝第一层 深拷贝(deepcopy): copy 模块的 deepcopy 方法,完全拷贝了父对象及其子对象.--克隆一份 原文地址:https://www.cnblogs.com/denny-djl/p/10348114.html

JS对象的浅拷贝与深度拷贝

1.js中的6个标准类型 原始类型:Undefined.Null.Boolean.String.Number 引用类型:Object ( 最简单的引用类型var obj={} ) 2.把标准类型分成了两类.这两种类型复制克隆有很大区别 原始类型:存储的是对象的实际数据( 存放在栈内存中 ) 引用类型:存储的是对象的引用地址( 栈内存中存放的堆内存的地址 ) 3.克隆概念 浅度克隆:原始类型为值传递.对象类型仍为引用传递 深度克隆:所有的元素与属性均完全复制.与原对象完全脱离关系( 对新对象的修改

浅拷贝与深度拷贝(原型模式)

Delphi的VCL从TPersistent开始支持RTTI(RuntimeTypeInfo)运行时类型信息,它是通过{$M+}编译指令提供了RTTI的功能.M打开以后,Delphi在编译该对象时,会把对象的类型信息编译进可执行文件,这样在运行时就可以动态地获得对象的属性和方法等信息.因为所有的VCL可视化组件都是从TPersistent派生的,因此可以将组件信息保存到dfm也可以动态加载. Delphi还定义了一个虚方法Assign, [delphi] view plain copy proc

Python直接赋值、浅拷贝和深度拷贝解析

ython 文件 writelines() 方法用于向文件中写入一序列的字符串. 这一序列字符串可以是由迭代对象产生的,如一个字符串列表. 换行需要制定换行符 \n. 语法 writelines() 方法语法如下: 1fileObject.writelines(iterable)参数 iterable -- 可迭代对象(字符串.列表.元祖.字典). 返回值 该方法没有返回值. 原文地址:http://blog.51cto.com/98405/2145034

拷贝构造,深度拷贝,关于delete和default相关的操作,explicit,类赋初值,构造函数和析构函数,成员函数和内联函数,关于内存存储,默认参数,静态函数和普通函数,const函数,友元

 1.拷贝构造 //拷贝构造的规则,有两种方式实现初始化. //1.一个是通过在后面:a(x),b(y)的方式实现初始化. //2.第二种初始化的方式是直接在构造方法里面实现初始化. 案例如下: #include<iostream> //如果声明已经定义,边不会生成 class classA { private: int a; int b; public: //拷贝构造的规则,有两种方式实现初始化 //1.一个是通过在后面:a(x),b(y)的方式实现初始化 //2.第二种初始化的方式是直

String 类的实现(2)深度拷贝详解

我们已经知道了浅拷贝存在的问题,即多次析构同一空间.这个问题是类的成员函数引起的,就是前面浅拷贝里相当于编译器自动合成的函数,确切的说,浅拷贝里的问题是由隐士拷贝构造函数和隐士赋值运算符引起的. 拷贝构造函数用于将一个对象拷贝到新创建的对象中.也就是说,他用于初始化过程中,最常见的是将新对象显式地初始化为现有的对象.每当程序生成了副本对象时,编译器也将使用拷贝构造函数.默认的拷贝构造函数逐个的拷贝非静态成员(即浅拷贝),拷贝的是成员的值.(由于按值传递对象将调用拷贝构造函数,因此应该按引用传递对