C++虚函数:
多态: 静态多态(重载)、动态多态(虚函数)
虚函数
虚函数表:编译器为每个类创建了一个虚函数表,类的每个对象共享一个虚函数表,对象的首地址存放了vptr
new/delete 和 malloc/free 的区别:
B树和B+树:
B和B+树的区别在于,B+树的非叶子结点只包含导航信息,不包含实际的值,所有的叶子结点和相连的节点使用链表相连,便于区间查找和遍历 B+ 树的优点在于:
由于B+树在内部节点上不包含数据信息,因此在内存页中能够存放更多的key。 数据存放的更加紧密,具有更好的空间局部性。因此访问叶子节点上关联的数据也具有更好的缓存命中率。
B+树的叶子结点都是相链的,因此对整棵树的便利只需要一次线性遍历叶子结点即可。而且由于数据顺序排列并且相连,所以便于区间查找和搜索。而B树则需要进行每一层的递归遍历。相邻的元素可能在内存中不相邻,所以缓存命中性没有B+树好。
B树的优点: 由于B树的每一个节点都包含key和value,因此经常访问的元素可能离根节点更近,因此访问也更迅速。
数据库索引采用B+树的主要原因是B树在提高了磁盘IO性能的同时并没有解决元素遍历的效率低下的问题。正是为了解决这个问题,B+树应运而生。B+树只要遍历叶子节点就可以实现整棵树的遍历。而且在数据库中基于范围的查询是非常频繁的,而B树不支持这样的操作(或者说效率太低)。
栈作用可以从两个方面体现:函数调用 和 多任务支持 。
hash_set/hash_map:
底层是有hash_table所封装实现的,hash_table(开链法解决冲突)的底层是由vector实现的,set/map底层是由RB tree实现的。
进程和线程的区别
线程是程序执行的最小单位,而进程是操作系统分配资源的最小单位;
一个进程由一个或多个线程组成,线程是一个进程中代码的不同执行路线
进程之间相互独立,但同一进程下的各个线程之间共享程序的内存空间(包括代码段,数据集,堆等)及一些进程级的资源(如打开文件和信 号等),某进程内的线程在其他进程不可见;
调度和切换:线程上下文切换比进程上下文切换要快得多
地址空间:同一进程的线程共享本进程的地址空间,而进程之间则是独立的地址空间。
资源拥有:同一进程内的线程共享本进程的资源如内存、I/O、cpu等,但是进程之间的资源是独立的。
进程独占的资源:地址空间、全局变量、打开的文件、子进程、信号量、账户信息
线程占有的资源:栈、寄存器、状态、程序计数器
一个进程崩溃后,在保护模式下不会对其他进程产生影响,但是一个线程崩溃整个进程都死掉。所以多进程要比多线程健壮。
进程切换时,消耗的资源大,效率高。所以涉及到频繁的切换时,使用线程要好于进程。同样如果要求同时进行并且又要共享某些变量的并发操作,只能用线程不能用进程
执行过程:每个独立的进程程有一个程序运行的入口、顺序执行序列和程序入口。但是线程不能独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
线程是处理器调度的基本单位,但是进程不是。 两者均可并发执行。
优缺点:
线程执行开销小,但是不利于资源的管理和保护。线程适合在SMP机器(双CPU系统)上运行。 进程执行开销大,但是能够很好的进行资源管理和保护。进程可以跨机器前移。
何时使用多进程,何时使用多线程?
对资源的管理和保护要求高,不限制开销和效率时,使用多进程。
要求效率高,频繁切换时,资源的保护管理要求不是很高时,使用多线程。
多进程 多进程通信:匿名管道(pipe),具名管道(FIFO)、消息队列、共享内存(单机内)、信号、sockets(跨主机)等 多进程同步:互斥器、条件变量、读写锁、文件锁、信号量
指针和引用(引用的本质是一个指针常量,所以引用指向是指针)的区别:
引⽤只能在定义时初始化⼀次,之后不能改变指向其它变量(从⼀⽽终);指 针变量的值可变。
引⽤必须指向有效的变量,指针可以为空。
sizeof指针对象和引⽤对象的意义不⼀样。 sizeof引⽤得到的是所指向的变量的 ⼤⼩,⽽sizeof指针是对象地址的⼤⼩。
指针和引⽤⾃增(++)⾃减(--)意义不⼀样。
相对⽽⾔,引⽤⽐指针更安全。
内存管理:
外部碎片->伙伴算法
伙伴算法(Buddy system)把所有的空闲页框分为11个块链表,每块链表中分布包含特定的连续页框地址空间:伙伴算法每次只能分配2的幂次页的空间,比如一次分配1页,2页,4页,8页,…,1024页(2^10)等等,每页大小一般为4K,因此,伙伴算法最多一次能够分配4M的内存空间。 申请和回收过程:
image
内部碎片->slab分配器
slab根据对象进行管理的,将内核中经常使用的对象 放到高速缓存中。
image
高速缓存链表cache_chain的每一个高速缓存都是由kmem_cache结构来描述,每个高速缓存都包含了一个slab列表,分别是: slabs_full(完全分配的 slab)、slabs_partial(部分分配的 slab)和slabs_empty(空 slab,或者没有对象被分配) slab是slab分配器的最小单位,单个slab可以在slab链表之间移动,例如如果一个半满slab被分配了对象后变满了,就要从slabs_partial中被删除,同时插入到slabs_full中去。