1.虚函数是怎么实现的
每一个含有虚函数的类都至少有有一个与之对应的虚函数表,其中存放着该类所有虚函数对应的函数指针(地址),
类的示例对象不包含虚函数表,只有虚指针;
派生类会生成一个兼容基类的虚函数表。
2.STL中map和set的原理(关联式容器)
map和set的底层实现主要通过红黑树来实现
红黑树是一种特殊的二叉查找树
1)每个节点或者是黑色,或者是红色
2)根节点是黑色
3) 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
4)如果一个节点是红色的,则它的子节点必须是黑色的
5)从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。
特性4)5)决定了没有一条路径会比其他路径长出2倍,因此红黑树是接近平衡的二叉树。
3.C++文件编译与执行的四个阶段
1)预处理:根据文件中的预处理指令来修改源文件的内容
2)编译:编译成汇编代码
3)汇编:把汇编代码翻译成目标机器指令
4)链接:链接目标代码生成可执行程序
4构造函数为什么不能是虚函数
5引用能否动态绑定,为什么
6.四种类型转换
7typedef和define的区别
8引用作为函数参数的好处
9引用作为返回值的好处
在内存中不产生被返回值的副本
10引用作为返回值的规则
不可对局部变量引用。
不返回函数内部new分配的内存的引用。
被函数返回的引用只是作为一 个临时变量出现,而没有被赋予一个实际的变量,那么这个引用所指向的空间(由new分配)就无法释放。
可以返回对类成员的引用,但最好是const。
流操作符>>和<<,赋值操作符=的返回值声明为他们的引用,这样,这些操作符可以连续使用。
加减乘除的操作符不能返回引用。
11野指针是什么,它产生的原因(未初始化,指向内存被释放但未给指针再指向,指针超过了变量了的作用范围,比如b[10],指针b+11)
12线程安全(加锁机制保护)线程不安全(不保护数据,多个进程先后更改,脏数据)
13内存泄漏的情况(1.newdelete2.delete[]3.虚析构函数)
14.栈溢出的原因(1.调用层次过深2.局部变量体积过大)
15list,vector区别(1.随机访问2.插入删除3.内存连续)
16函数调用
开辟函数的栈空间
实参复制值到形参(具体分析:值传递,引用传递,指针传递(形参指针指向实参的内存))
运算
调用结束,形参弹出栈空间(指针传递:形参指针销毁,但所指内存依然存在)
17互斥锁,条件锁,读写锁
18宏与inline区别
预处理阶段,编译阶段,
字符替换,控制转移
参数和返回值检查
19ifndef/define/endif
20左值引用,右值引用区别
左值引用,通常说的引用,给变量起别名。
右值引用,绑定到右值,使原本快要被销毁的右值,的生命期,延长到右值引用的生命期。
在有拷贝构造和移动拷贝构造函数的时候,优先调用了移动拷贝构造和移动赋值。移动拷贝不重新开辟内存,直接移动资源。
21值传递,引用传递,指针传递
值传递:形参是实参的拷贝,改变形参的值并不会影响外部实参的值。从被调用函数的角度来说,值传递是单向的(实参->形参)只能传入,不能传出。
引用传递:形参相当于是实参的“别名”,对形参的操作是对实参的操作。被调函数的形参也作为局部变量在栈中开辟了内存,但这时存放的是由主调函数放进来的实参变量的地址。
指针传递:指针传递参数本质上是值传递的方式,它所传递的是一个地址值。给指针类型的形参开辟了内存,但传递进来的时地址。形参改变会影响实参。(考虑另一种情况:如果传进来的是指针)
22引用作为函数参数的特点
1.效果和指针传递类似,形参改变影响实参。
2.效率高,因为不会产生实参的副本,是直接对实参操作。
23.重写(覆盖),重定义(隐藏同名),重载
24.只使用初始化列表的情况
- const常量成员,因为常量只能在初始化,不能赋值,所以必须放在初始化列表中;
- 引用类型,引用必须在定义的时候初始化,并且不能重新赋值,所以也要写在初始化列表中;
- 没有默认构造函数的类类型,因为使用初始化列表可以不必调用默认构造函数来初始化,而是直接调用拷贝构造函数;