1.POD类型是只包含数据的结构体类型,没有方法,把它看作是一个数据集合时,就是POD类型
2.对于内置类型来说,没有拷贝构造函数和析构函数
3.#include
#include
#include
4.STL把建立对象和析构对象分成一组,申请空间和释放空间分成一组
5.对象建立前的空间配置,和对象析构之后的空间释放,由#include
①向系统的堆区申请空间
②考虑多线程的情况
③考虑内存不足的情况
④考虑小块能存可能造成内存碎片的情况
6.new在申请失败时会抛出异常,malloc在申请失败时返回空指针(0指针)
7.SGI设计了双极配置器,第一级配置器直接使用malloc和free,第二级配置器则按情况采取不同的策略,如果内存块大于128字节,则视为足够大,就使用一级配置器,如果内存块小于128字节,则视为足够小,则采用内存池方式,而不再求助于第一级配置器,
8.堆区分为两个部分,一个是小块内存存取,一个是大块内存存取,就是说如果开辟的少,就从小块内存中存取,如果开辟的比较大,就从大块的内存中存取
9.堆区的管理方式和一级配置器二级配置器是完全一样的,没有什么区别
10.二级配置器称为默认配置器,如果申请的空间小于128字节,就从内存池中取,如果申请的空间大于128,就调动一级配置器
所以如果开放二级配置器也是有可能转到一级配置器的
11.定义一个list,list mylist;然后插入了一些数据,现在执行mylist.pop_back();删除节点,那么删除完后,这个节点的空间是否返回给系统了呢?
答案:在STL中,内存池分为两级,在申请节点的时候,如果申请节点的大小小于等于128字节,它是从二级配置中的内存池中分配的空间,那么释放完以后就会把空间还给内存池,并没有返还给堆区,如果申请节点的时候,申请节点的大小大于128字节,那么释放完以后,就会把空间还给内存池
12.定义一个vector,在pop_back()后,会把空间还给堆区吗?
答案:不会,vector是连续分配空间的,如果空间大小小于等于128,是从内存池中分配空间,尽管pop_back()了,但是仍然不会把空间换个内存池,只有当对象死亡的时候,才会把整个vector的空间还给内存池,如果空间大小大于128,就还给堆区
13.一级配置器__malloc_alloc_template剖析
14.静态成员初始化,静态函数指针初始化,静态变量初始化
15.一级配置器处理内存不足的核心思想,假设在申请空间之前,已经申请了一块很大的空间,当申请空间的时候,如果空间足够,则正常分配空间,如果空间不足,判断之前申请的空间是否为空,即是否还存在,如果存在,就把之前申请的很大的空间释放掉,然后将指向该空间的指针置为null,表示该空间已经释放掉了,如果这时空间够了,则分配空间,如果判断之前申请的空间不存在,则打印出错误或者什么,有自己来定义
16.二级配置器多了一些机制,避免太小的内存块造成内存泄露的问题,小的内存块带来的不仅仅是内存碎片的问题,配置时也带来了额外的负担,负担永远无法避免,如果申请的空间越小,额外负担所占的比例就越大,空间浪费就越大
17.当malloc(1)的时候,并不意味着就从内存中分配1字节的空间,上面是有4个字节的上越界标记,下面也有4个字节的下越界标记,上面还有一个信息的头部,头部中有一个值记录的当时申请了多大的空间,还有next域和pre域,连接到链表中,在上面或者下面还有一个标记(在不同的系统位置不一样),标记是否释放,释放的时候看如果没有释放,那就释放,如果已经释放了,就不释放了
所以,申请的空间越小,这些额外的负担也就占的越大
malloc函数在调用的时候,速度太慢了,这就导致我们要使用内存池,要消去这些额外的负担,加快申请空间的速度
18.为了方便管理,SGI二级配置器将任何小块内存都上调至8个倍数
加入申请了10号区域的内存块,它就把10号区域的链表从头删除一个节点交给用户,释放的时候再还回来
012…15每个都是一个指针
每个区域的块与块之间是通过free_list_link链接起来的
分配块的时候是头删,归还块的时候是头插
19.volatile关键字
20.reallocate必须要会,处理的方法很巧妙
21.引用是指针的语法糖,lambda表达式是仿函数的语法糖
加入要通过函数修改变量a的值,如果使用指针,则需要在函数内部进行指针判空的操作,而如果使用引用的方式,则不要进行判空操作,所以引用是指针的语法糖
fun(int* p)
{
if(p != NULL)
{
*p += 10;
}
}
fun(int& p)
{
p += 10;
}
int main()
{
int a = 0;
//fun(&a);
fun(a);
return 0;
}



