内存笔记

内存

  • 计算机的作用

    • 用来计算和存储二进制的数据

  • 问题:计算机如何计算1+2

    • 转换成二进制的数值

    • 在计算机中开辟两块内存空间

    • 将1和2存储到这两块内存空间中

  • 变量的概念

    • 变量就是引用.变量其实表示的就是计算机中的一块内存

      • 严谨:变量其实就是内存地址

    • 一块内存空间会有两个默认属性

      • 内存空间大小

        • bit

        • byte

        • kb...

      • 内存地址

        • 作用:寻址

    • int类型的变量默认开启4个字节空间大小的内存地址

  • 理解a=10的内存图(引用,指向)

    • 指向:如果变量或者引用存储了某块内存空间地址,则该变量或者引用指向该块内存

  • 不同数据占用内存空间的大小不同

顺序表

  • 数组中的数据类型为什么要一致?

    • 数组在内存中是以链表的方式进行存储,会在内存中连续开辟一个空间给元素进行存储.比如数组中存储了a = array([1,2,3]),那么会在内存中连续开辟3个空间,变量a指向第一个空间地址也就是元素1的存储地址,暂且空间地址记为0x0.整型在内存中默认开辟4个字节大小,那么1向后偏移4个字节为2,内存地址记为0x4,同理元素3为0x8.所以只需记录了第一个元素1的内存地址,那么只要向后偏移以4位单位的字节就能找到连续开辟内存空间的其他元素.

  • 为什么数组索引从0开始?

    • 为了更方便的让计算机进行变量寻址和偏移.

    • a[0] -> 0-> 0x0

    • a[1] -> 1-> 0x4

    • a[2] -> 2-> 0x8

  • 在顺序表中的插入和删除操作浪费性能

    • 列表或数组中有300W个元素,如果我在第二个位置插入或者删除1个元素,那么后面的299W个元素的内存地址都将向前或向后一位,很浪费性能.

  • 数组与列表的区别

    • 数组:数组在内存中为元素开辟的空间是连续的

    • 列表:列表在内存中为元素开辟的空间是非连续的,但它有另外一个连续的空间顺序的存放元素对应的地址

  • 单数据类型顺序表的内存图(内存连续开辟)

  • 多数据类型顺序表的内存图(内存非连续开辟)

  • 顺序表的弊端:顺序表的结构需要预先直到数据大小来申请连续的存储空间,而在扩充时又需要进行数据的搬迁.

python内存管理机制

  • 1.计数器

    • a=10,b=a(a的引用计数为2) del b(引用计数-1) del a(引用计数为0)

  • 2.垃圾回收

    • 引用计数为主,标记清除和分代回收为辅

    • 标记清除:

      • a = [1,2] b = [3,4] a.append(b) b.append(a) 当a和b形成环状引用且引用计数都为2,当我del a del b时,它们的引用计数都为1,但此时已经删除了变量a和b,但它们的值还是存在内存中并且不能被使用,变成了垃圾.标记清除就是为了解决这种情况,把它们两个的引用计数都-1.

    • 分代回收:

      • 存在3个列表分为0代,1代和2代.轮询这3个列表,查看变量的引用计数是否为1和环状引用

        • 0代:当长度大于700时进行轮询

        • 1代:每扫描10次0代进行扫描1次1代

        • 2代:每扫描10次1代进行扫描1次2代

  • 3.内存池:

    • 小数据池

  • 1.开启一个新的对象会存放在双端链表中

  • 2.通过引用计数来确定是不是垃圾,但是会有循环引用的问题

  • 3.为了解决循环引用,使用了标记清除,标记清除就是将循环引用的内容引用计数都-1

  • 4.为了解决多次扫描一个双端链表,使用了分代回收.一共是3代,0、1、2代

  • 5.当0代的长度>700时扫描一次0代,每扫描10次0代就会扫描1次1代

  • 6.每扫描10次1代就扫描1次2代

原文地址:https://www.cnblogs.com/zyc1013/p/12060971.html