python和c++的区别以及python回收机制

  1. 语言类型
    python是一种基于解释器的语言,解释器会逐行读取代码;首先将python编译成字节码,然后由C程序解释.
    C++是一种编译语言,在其他章节里写过,整个过程是编译器编译代码成汇编语言,汇编语言由汇编器生成机器码,之后还要经过链接器载入文件\库等指令生成可执行代码,最后装载器将可执行代码和数据载入内存,CPU读取内存执行.

  2. 内存管理
    python由自动垃圾收集器进行内存管理.
    c++中程序员必须自己进行内存管理.

  3. 速度
    python由全局锁,多线程效果不好
    c++运行效率很高

python 垃圾回收机制

  1. 引用计数
    python的垃圾回收机制主要是引用计数为主,分代回收为辅. 引用计数就是每个对象维护一个ob_refcnt,用来记录当前对象被引用的次数.
    当出现下面的情况时引用+1:
  • 对象被创建 a=1
  • 对象被引用 c=b
  • 对象被当作参数传入函数中 func(a)
  • 对象被作为元素存储在容器中时 List=[a,b] Dict={a:1}

下面四种情况引用减一:

  • 当对象被显式销毁 del a
  • 当对象被赋予新的对象 a=2
  • 当对象离开作用域,如func执行完之后,函数内的局部遍历引用计数器就都会减一
  • 当元素从容器中删除或者容器被销毁

当计数器减到0,那么该内存就会被python虚拟机销毁.

缺点:

  • 消耗资源,需要维护计数器的资源.
  • 无法解决循环引用的问题,和shared_ptr一样出现了循环引用无法正常回收
list1=[]
list2=[]
list1.append(list2)
list2.append(list1)

上面的结果是 list1=[[[[[…]]]]] list2=[[[[[…]]]]]

  1. 标记删除

『标记清除(Mark—Sweep)』算法是一种基于追踪回收(tracing GC)技术实现的垃圾回收算法。它分为两个阶段:第一阶段是标记阶段,GC会把所有的『活动对象』打上标记,第二阶段是把那些没有标记的对象『非活动对象』进行回收。那么GC又是如何判断哪些是活动对象哪些是非活动对象的呢?
对象之间通过引用(指针)连在一起,构成一个有向图,对象构成这个有向图的节点,而引用关系构成这个有向图的边。从根对象(root object)出发,沿着有向边遍历对象,可达的(reachable)对象标记为活动对象,不可达的对象就是要被清除的非活动对象。根对象就是全局变量、调用栈、寄存器。

这个方法就是通过根节点找出可达和不可达的节点组,不可达的节点组就是相互引用或者等待释放的.
python和c++的区别以及python回收机制_第1张图片

在上图中,我们把小黑圈视为全局变量,也就是把它作为root object,从小黑圈出发,对象1可直达,那么它将被标记,对象2、3可间接到达也会被标记,而4和5不可达,那么1、2、3就是活动对象,4和5是非活动对象会被GC回收。

标记清除算法作为Python的辅助垃圾收集技术主要处理的是一些容器对象,比如list、dict、tuple,instance等,因为对于字符串、数值对象是不可能造成循环引用问题。

  1. 分代回收

首先建立了一个链表,把创建的对象都加入,这个链表是Generation Zero.
随后,Python会循环遍历零代列表上的每个对象,检查列表中每个互相引用的对象,根据规则减掉其引用计数。减到0的对象就可以被释放,不是0的对象就会被移动到一代链表中.
循环上面的过程,如果一代链表中存活下来的就会被放入二代链表.

这个循环遍历多久执行一次呢? 根据一个GC阈值来判断,即当分配的计数器计数到某个阈值就开始遍历.

分代的好处: 保留了长期留存的对象,这些对象就大概率很久才会被释放,因此遍历的频次可以减少.
这种行为的理论是弱代假说年亲的对象通常死得也快,而老对象则很有可能存活更长的时间。

将系统中的所有内存块根据其存货的时间划分为不同的集合, 每个集合就成为一个”代”, 垃圾收集的频率随着”代”的存活时间的增大而减小(活得越长的对象, 就越不可能是垃圾, 就应该减少去收集的频率)

你可能感兴趣的:(面经,c++,python)