C++与Python的深浅拷贝比较

C++的内存管理

代码区(程序的执行代码)
数据区(全局变量、常量、静态变量)
堆区(动态内存)
栈区(程序中用到的局部数据)

数据区细分为:自由存储区、全局/静态存储区、常量存储区

所以就有5个数据存储区:

栈区(stack),在执行函数时,函数内的局部变量的存储单元都可以在栈上创建,函数结束后这些内存单元自动被释放。

堆区(heap),由new分配的内存块,一般一个new对应一个delete,如果程序员没有释放,则在程序运行完后,操作系统自动回收

自由存储区,由malloc等申请,由free释放

全局/静态存储区,全局变量和静态变量存放在同一块内存中

常量存储区,里面存放的是常量,不允许修改


c++的浅拷贝(使用编译器默认的复制构造函数、或缺省的复制运算符)

class A a;

b=a;

b对象copy a对象在stack区的数据,但是并不copy a对象在heap区的数据,而是与a共用heap区的数据


如果对象有位于heap上的域的话,其不会为拷贝对象分配heap上的空间,而只是指向相同的heap上的同一个地址


C++中会调用拷贝构造函数的情况:

  • 一个对象以值传递的方式传入到函数体
  • 一个对象以值传递的方式从函数中返回
  • 一个对象需要另一个对象初始化


Python的内存管理

在Python中,对象都是通过引用传递的不存在按值传递,Python使用引用计数来跟踪内存中的对象:当一个对象被创建时,就创建了一个引用计数,当这个对象的引用计数为0时,该对象就会被垃圾回收

什么情况在会增加对象的引用计数?

  • 对象被创建,如x=1
  • 或另外的别名被创建,如y=x
  • 或作为参数传递给函数,如 func(x)
  • 或作为容器对象的一个元素,如alist=[x,1,'abc']

什么情况下会减少对象的引用计数呢?

  • 局部变量离开其作用域
  • del y
  • 对象被重新复制,x=123
  • 对象从一个窗口对象中移除,alist.remove(x)
  • 窗口被销毁,del alist

Python浅拷贝的方式(非容器类型的对象没有被拷贝的说法,比如:数字,字符串和其他“原子”类型的对象):

1.完全切片[:];2.使用工厂函数,list(),dict()等;3.使用copy函数

Python深拷贝的方式:使用copy.deepcopy()函数


浅拷贝过程:

对于非容器类类型的对象(字符串,数字)或非可变类型的对象(tuple)中的元素直接复制;对于容器类且可变的(如list,dict)对象里的元素只是把它的引用进行复制。

<pre name="code" class="python"><span style="font-size:14px;">>>> a=[1,'a',['this is a',11]]
>>> b=a[:]
>>> b[0]=2
>>> b[1]='b'
>>> b[2][0]='this is b'
>>> b[2][1]=22
>>> a,b
([1, 'a', ['this is b', 22]], [2, 'b', ['this is b', 22]])</span>

 

b[0]和b[1]的改变并不会影响a[0],a[1]因为其中的元素1,‘a’都是常量对象,是不可变类型;但是b[2]的改变却会影响a[2],因为该对象是list,是可变对象,因此b[2]只是对a[2]的引用。


注意:如果上述b=a,则表示b是a的引用,a的引用计数+1;此后b的任何动作都会影响a,因为它们指向的是同一块地址。等于号操作并不是浅拷贝,只是传递引用而已


深拷贝过程:创建一个新的容器对象,并对原来对象中的所有元素进行全新的拷贝

<span style="font-size:14px;">>>> a=[1,'a',['this is a',11]]
>>> import copy
>>> b=copy.deepcopy(a)
>>> b[0]=2
>>> b[1]='b'
>>> b[2][0]='this is b'
>>> b[2][1]=22
>>> a,b
([1, 'a', ['this is a', 11]], [2, 'b', ['this is b', 22]])</span><span style="font-size: 14px;">
</span>


上述b对象的任何改变都不会影响a。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值