每天学习亿点点: 8.29 STL和内存管理 (hj老师yyds)

STL篇:

1. STL六大部件

容器,分配器,算法,迭代器,适配器,仿函数

适配器的本质实际上是用另一个容器在内部干活但是对外表现是另一种容器的行为模式

分配器就是给分配内存的

迭代器就是一种智能指针,用来模拟指针的行为并更加安全的访问容器内容

算法是作用在容器内容上的,比如排序,找某个值等等功能

仿函数是一些object, 通过仿函数适配器传给算法就可以用来做特定的操作,比方说排序,传到算法里面的就是一个函数object

  

比如这张图里显示的.

2.几种iterator的定义

 

traits 其实就是用来告诉我们某个类的一些我们关心的信息的,比如我们在算法中需要知道这次使用的一个容器中的iterator到底是随机读取的还是顺序读取的....

 3. VC6里面使用的分配器


其实啥也没做,还是调用的new delete表达式而已


4. G2.9使用的分配器


 

我们这里就可以看到,这个版本里用到了非常多的内存分配的手段,非常适用于小空间分配管理

5. iterator的前闭后开


6.G4.9的分配器


这个版本有很多额外的分配器,其中__pool_alloc就是G2.9的alloc


7. 容器结构与分类



其中两个adaptor就是stack和queue, 其实内部就是dequeue实现的


8. list 的 iterator



*this 肯定就直接解释成iterator类型啊,因为this本身就是iterator类新的指针啊. 


9. 容器list



10. iterator需要遵循的原则和五种必须提供的信息








11. Traits其实就是利用的是偏特化的特性


每一个偏特化版本的类进行单独编写,这样就做到了分类且记录信息

traits有各种类型可以告诉我们某个类的很多信息,比如是不是一个类,是不是char类,int类型?等等这种可以通过类型推断获得的信息



12. Vector及其iterator


vector的 iterator就是_Tp*外部覆盖一个iterator adaptor来支持5 种关联类型


13.Deque

Dequeue是从中间向左右两边生长的容器,这种容器是采用分块方式进行增长的,一个iterator不仅要知道本块的位置还要知道每个块中的填充情况. 除此之外还有一个管理所有iterator块的控制单元map,map中存放了所有iterator

需要注意的是这个容器中iterator包含了四个部分:

cur: 在本块中的最新位置,在start和finish里面体现了前闭后开

first: 本块中的第一个

last: 本块中的最后一个

first和last依旧遵循前闭后开的准则

node: 指示的是该node在map中的位置,总是在左边


Dequeue其实是用iterator来模拟连续空间的,它根本就不是连续空间, 通过重载*, -> ,- , +=,+ 号来进行假的连续空间表现

deque采用的也是大名鼎鼎的pimpl idom进行类的接口和实现的解耦
















14. Queue


Queue实际上就是底层用deque写的, Queue只是个适配器


15. Queue和Stack



Stack和queue不允许遍历和提供iterator

stack和queue都可以用list和deque实现,但是stack只能是vector实现,queue不能,因为讲究个先进先出

当然不能使用关联性容器set或者map做底层结构




16. 容器rb_tree








17. Set, MultiSet



Key 就是Value,Value就是Key

Set必须独一无二

MultiSet可以多个重复值


18.Map和MultiMap




Map和MultiMap都不能改变已经插入的Key

禁止对插入的元素Key值赋值

Map不能出现重复的Key

MultiMap却可以重复的Key



19. HashTable



Hashtable简单来讲就是把一系列数据重新编号然后放进一个桶里,这样查找的速度会快很多,但是出现计算之后编号一样的情况时,需要解决,这就是所谓的哈希冲突





最好计算之后的编号越乱越好



mod运算是几乎都会用到的运算


20. Unordered容器


unordered其实都可以换成hash, 就是C++11之前的hash啦






21.C++标准库算法是啥



算法就是要作用在容器上的,这个时候算法需要知道这个容器的基本信息,而知道这个基本信息的只有iterator了. 

22.Iterator的几种category



五种iterator_category

forward其实就是可以++的

bidirectional其实就是可以++和--的

random其实就是可以[]重载的


23. 各种容器的iterator的category的typeid其实都蛮怪的, 因为编译之后都会添油加醋的

24. istream_iterator 和ostream_iterator的category




25.Iterator_category 和type_traits 对于算法的影响

其实基本是对于算法行为是会有很大的影响的


26. 算法源码中关于category的一些暗示


其实就是用名字来直接告诉调用者我要哪种类型的容器去进行操作


27.算法accumulate




28.算法for_each

29.算法replace, replace_if, replace_copy



30.算法count, count_if

31.算法find, find_if




32.算法sort


33.关于reverse iterator, rbegin(), rend()

34.算法binary_search


35.仿函数





36.多种adaptor


其实就是用别人帮我们干活而已就这样,超简单


37.binder2nd


其实就是对某个functor的第二个参数进行绑定固化而已


38.not1 


其实就是把结果not一下

39.新型适配器bind




40.迭代器适配器reverse_iterator

41.迭代器适配器inserter



42. X适配器 ostream_iterator和istream_iterator

 

43.一个万能hash_function

44.Tuple

45.Type traits


全一般偏特化实现的


46.cout

47.moveable元素对一些容器效率的影响

简单来讲就是在move构造的时候会有很大的性能改变










内存管理篇:

1.内存管理的层次机构

2.内存原始操作

3.new expression

只有编译器才可以像那样直接呼叫ctor, 其他的都不行.

4.delete expression

5.array new, array delete, array size, array delete, in memory block

6. placement new

7.C++应用程序, 分配内存的途径

8.C++容器, 分配内存的途径

9. 分配内存的全局::operator new 和::operator delete可以重载

10.类成员函数分配内存的operator new和delete


如果不在类里写自己的new和delete就会调用全局的,所以需不需要覆盖自己决定

11.Per-class allocator

这里有个内嵌指针的概念,其实就是用的时候装内容,不用的时候当指针指向下一个内存块


12.static allocator



把内存功能全部交给另一个类去完成.

13.Global allocator 多个free list的管理很复杂




14.new handler

这个是用来处理交不出内存时的情况,new handler就是用来处理这种特殊情况的函数句柄

15.=Default,=Delete

16.VC6标准分配器的实现


VC6的标准器的实现只是用了operator new和operator delete 完成allocate和deallocate

17.BC5标准分配器的实现

也是一样的偷懒设计



18.G2.9, std::alloc

std::allocator是偷懒设计

但是std::alloc是那个非常好用的精妙的那个

G2.9的std::alloc在G4.9中就是__pool_alloc

其实这个allocator就是在维护很多个list,每个list放的都是同一种大小的内存块需求的比方说:

8,16,32,64,128….etc.

中间就用embedded pointer方法来做的

19. std::alloc运行模式和源码剖析

20.std::alloc的好与坏


坏: 写代码声明变量不要太迷惑

obj** p1,p2. 

一个是二级指针一个是一级指针

void (*SetHandler(void (*f)()))(int); 其实就是参数为void (*f)()返回值为void (*g)(int)的函数指针

最好是用时再定义,不要上来就定义初始化

好习惯: if(constexpress==xXXXX)

因为左边是常量值无法赋值,所以可以让编译器帮你检测错误


21.VC6内存分配


其实这个版本的内存分配基本也是alloc那个分配器的做法,只不过是增加了更复杂的控制机制,基本思想都一样

简而言之就是32个tagheader

每个header里面有个region并对这个region进行管理统计

每个region里面有32个group

每个group里面有64个taglisthead

每个taglisthead里又有前置entry和后置entry

每个entry其实就是指向前置和后置entry的类型而已



22.Loki allocator



23.GNU对于Allocator的描述

24. VS2013 标准分配器与new_allocator

25.G4.9标准分配器与new_allocator


26.G4.9 malloc_allocator 

27.array_allocator

28.debug_allocator

29. G2.9容器使用的分配器不是std::allocator而是std::alloc

30.pool_allocator

31.bitmap_allocator

32.使用G4.9分配器

posted @ 2021-08-29 12:05  Tonarinototoro  阅读(76)  评论(0编辑  收藏  举报