C++经典面试题

Posted by Tango on January 18, 2018

linux常考命令

抓包工具
		# tcpdump
查看进程通信的信号量、共享内存、管道情况
		# ipcs/ipcrm
查看cpu信息
      # cat /proc/cpuinfo
查看内存信息    
      # cat /proc/meminfo
查看硬盘信息
      # df -lh
更详细的信息
      # cat /proc/scsi/scsi
查看网卡信息
     # dmesg | grep eth

更常用的命令(显示系统核心版本号、名称、机器类型等)

       # uname -a

动态链接和静态链接

静态链接与动态链接:

静态链接方法:#pragma comment(lib, "test.lib") ,静态链接的时候,载入代码就会把程序会用到的动态代码或动态代码的地址确定下来
静态库的链接可以使用静态链接,动态链接库也可以使用这种方法链接导入库

动态链接方法:LoadLibrary()/GetProcessAddress()和FreeLibrary(),使用这种方式的程序并不在一开始就完成动态链接,而是直到真正调用动态库代码时,载入程序才计算(被调用的那部分)动态代码的逻辑地址,然后等到某个时候,程序又需要调用另外某块动态代码时,载入程序又去计算这部分代码的逻辑地址,所以,这种方式使程序初始化时间较短,但运行期间的性能比不上静态链接的程序。

在软件开发的过程中,大家经常会或多或少的使用别人编写的或者系统提供的动态库或静态库,但是究竟是使用静态库还是动态库呢?他们的适用条件是什么呢?

简单的说,静态库和应用程序编译在一起,在任何情况下都能运行,而动态库是动态链接,顾名思义就是在应用程序启动的时候才会链接,所以,当用户的系统上没有该动态库时,应用程序就会运行失败。再看它们的特点:

动态库:

1.共享:多个应用程序可以使用同一个动态库,启动多个应用程序的时候,只需要将动态库加载到内存一次即可;

2.开发模块好:要求设计者对功能划分的比较好。 

静态库:代码的装载速度快,执行速度也较快,因为编译时它只会把你需要的那部分链接进去,应用程序相对比较大。但是如果多个应用程序使用的话,会被装载多次,浪费内存。

_exit()和exit()

 _exit()函数的作用最为简单:直接使进程停止运行,清除其使用的内存空间,并销毁其在内核中的各种数据结构;exit() 函数则在这些基础上作了一些包装,在执行退出之前加了若干道工序,也是因为这个原因,有些人认为exit已经不能算是纯粹的系统调用。

exit()函数与_exit()函数最大的区别就在于exit()函数在调用exit系统调用之前要检查文件的打开情况,把文件缓冲区中的内容写回文件,就是"清理I/O缓冲"。   

单继承内存结构

单继承中(一般继承),子类会扩展父类的虚函数表。在多继承中,子类含有多个父类的子对象,该往哪个父类的虚函数表扩展呢?当子类overwrite了父类的函数,需要覆盖多个父类的虚函数表吗?

1) 子类的虚函数被放在声明的第一个基类的虚函数表中。

2) overwrite时,所有基类的print()函数都被子类的print()函数覆盖。

3) 内存布局中,父类按照其声明顺序排列。
其中第二点保证了父类指针指向子类对象时,总是能够调用到真正的函数。

###C++变量的初始化

对于内置类型局部变量不进行初始化,但是分配地址,全局变量会进行默认初始化。

对于类类型局部变量(没有显式初始化)会进行默认初始化(有默认构造函数,否则报错),但其内部的内置数据成员不会进行初始化(如果在默认构造函数没有进行初始化)。数组也是同样。

static为什么不能是const修饰?

静态成员函数是属于类的,而不是某个具体对象,在没有具体对象的时候静态成员就已经存在,静态成员函数不会访问到非静态成员,也不存在this指针。而成员函数的const就是修饰this指针的,既然静态成员函数不会被传递this指针,那const自然就没有必要了

C++ 内存管理

内存分配方式:  
在C++中,内存分成5个区,分别是堆、栈、自由存储区、全局/静态区和常量存储区.

1) 栈:存放函数参数以及局部变量,在出作用域时,将自动被释放.栈内存分配运算内置于处理器的指令集中,效率很高,但分配的内存容量有限.

2) 堆:new分配的内存块(包括数组,类实例等),需delete手动释放.如果未释放,在整个程序结束后,OS会帮你回收掉.

3) 自由存储区:malloc分配的内存块,需free手动释放.它和堆有些相似.

4) 全局/静态区:全局变量(global)和静态变量(static)存于此处.(在以前的C语言中,全局变量又分为初始化的和未初始化的,C++不分)

5) 常量存储区:常量(const)存于此处,此存储区不可修改.

IP报文

TCP报文

红黑树和AVL

红黑树定义:
1) 每个结点或者为黑色或者为红色。

2) 根结点为黑色。

3) 每个叶结点(实际上就是NULL指针)都是黑色的。

4) 如果一个结点是红色的,那么它的两个子节点都是黑色的(也就是说,不能有两个相邻的红色结点)。

5) 对于每个结点,从该结点到其所有子孙叶结点的路径中所包含的黑色结点数量必须相同。

AVL定义:
一棵AVL树满足以下的条件:
1) 它的左子树和右子树都是AVL树
2) 左子树和右子树的高度差不能超过1
性质:
1) 一棵n个结点的AVL树的其高度保持在0(log2(n)),不会超过3/2log2(n+1)
2) 一棵n个结点的AVL树的平均搜索长度保持在0(log2(n)).
3) 一棵n个结点的AVL树删除一个结点做平衡化旋转所需要的时间为0(log2(n)).


比较:
1) 红黑树并不追求“完全平衡”——它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
2) 红黑树是牺牲了严格的高度平衡的优越条件为代价红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。