博客参考:C++中的多态和内部实现:https://www.cnblogs.com/qiaoconglovelife/p/5128523.html
虚函数表存放的地址:https://blog.csdn.net/jiary5201314/article/details/52627630
为什么STL和linux都采用红黑树作为平衡树的实现:https://www.zhihu.com/question/20545708
进程关系:父子进程之间的数据共享:http://blog.sina.com.cn/s/blog_1550922e60102z7gm.html
(1)C++语言中多态的实现:一个接口,多种行为(向不同对象发送同一消息,可以产生不同的行为)
1)编译时多态:函数的重载和模板实现,编译器在编译的时候,通过实参的个数和类型,选择最终调用的函数;
2)运行时多态:通过虚函数实现,基类的某个成员函数为虚函数,派生类又定义一成员函数,除函数体的其余部分都与基类的成员函数相同;
每一个含有虚函数的类,都会生成虚表(virtual table)。这个表,记录了对象的动态类型,决定了执行此对象的虚成员函 数的时候,真正执行的那一个成员函数。
对于有多个基类的类对象,会有多个虚表,每一个基类对应一个虚表,同时,虚表的顺序和继承时的顺序相同。
在每一个类对象所占用的内存中,虚指针位于最前边,每个虚指针指向对应的虚表。
3)虚指针存放在内存的哪里:虚函数表是全局共享的一个元素,即全局只有一个,存放在内存的静态/全局变量区。
函数表类似一个数组,类对象中存储vptr指针,指向虚函数表.即虚函数表不是函数,不是程序代码,不肯能存储在代码段.。
.虚函数表存储虚函数的地址,即虚函数表的元素是指向类成员函数的指针。
(2)STL容器的底层实现:
1)map的底层实现用红黑树,而不用AVL
a)AVL是一个高度平衡的树,对树进行插入和删除更容易导致树的unbalance,因此AVL需要rebalance的概率更大,AVL插入最多也只需要两次旋转;而红黑树插入只要两次旋转,删除至多三次旋转;虽然使用AVL树搜索的效率非常稳定,但选取红黑树,是一个折中的方案;
b)插入一个节点导致树的不平衡,AVL和红黑树都最多只需要两次旋转操作;但删除节点引起树的不平衡,最坏情况,AVL需要维护从被删节点到root这条路径上所有节点的平衡性,因此旋转量级为O(logN),而红黑树至多需要三次旋转;
c)红黑树在需要大量插入和删除节点的场景下,效率更高;AVL由于高度平衡,所有搜索的效率更高;
d)map的实现是折中了两者在搜索,插入,删除的效率,总体来说红黑树更好;
(3)ucos操作系统和linux操作系统的区别
参考博客:ucos ii和linux操作系统的区别:https://blog.csdn.net/chen_geng/article/details/51556459
(4)全局变量在多任务之间可以共享吗?
1)对于多进程而言(父子进程和兄弟进程):如果其中一方调用了exec族函数(进程的代码和数据,全部替换,实际使用的物理内存也会重新申请),此时进程的代码段,数据段和堆栈都是独立的,没有任何关系;
2)对于父子进程,其全局变量遵循“读时共享,写时独享”的原则,因此,如果在父子进程中有修改全局变量的情况,系统会再给变化的全局变量分配不同的物理内存;
3)对于不同进程的线程,不能通过全局变量来通信;
4)对于同一进程的线程,可以通过全局变量来铜线的,它们共享进程的代码段、数据段、BSS段。页目录和页表使用进程的页目录和页表;
(5)进程之间共享的内容有哪些?
1)对于没有联系的进程之间的数据是相互独立的;
2)对于父子进程:相同的地方:全局变量,堆栈,环境变量,用户id,宿主目录,进程工作目录,信号处理方式;
不同的地方:进程id,fork返回值,父进程id,进程运行时间,闹钟,未决信号集;
可以理解成,子进程拷贝了父进程0~3G用户空间的内容,以及父进程的pcb,但是pid不同,然后再映射到物理内存;
(6)虚拟内存和物理内存的映射
参考博客:虚拟地址和物理地址的转换:https://blog.csdn.net/a8316124/article/details/56485642