C++面试总结
1.普通成员函数可以作为线程的入口函数吗?##
不可以,但是可以传递一个static的成员方法,再在这个static成员方法中调用普通的成员函数,或者将一个普通的成员函数申明为友元函数,用这个友元函数可以传给线程入口。
2.vector和list的区别,哪个随机访问更快,哪个插入更快,在尾部插入哪个更快##
- 由于vector基于连续内存的数组,所以它的随机存取非常快,但是插入和删除就会很耗时,插入删除会重新拷贝内存,若内存空间不足还会重新申请内存。
- list是基于双向链表,所以它的删除和插入很快,但随机存取很慢。如果实在尾部插入,用list更合适,如果用vector的话可能导致空间不足而重新生成一片空间,在将数据完全拷贝过去。
- map是键值对,基于红黑树,有自动排序的功能,存储字典的时候很适用
- set是集合,并且set中不会包含重复元素,内部使用平衡二叉树实现,便于元素查找。
- deque队列,支持随机存取,而且在两端的操作速度和list相差不大
3.线程同步时,死锁是如何产生的##
一个线程需要多个加锁资源时,可能导致死锁的产生。例如线程1,2都需要资源A和B,当线程1获取到资源A,线程2获取到资源B,此时线程1等待线程2释放资源B,但是线程2又在等待线程1释放资源A,这时死锁就产生了。
4.写文件到磁盘的过程##
先将数据写入缓冲区,如果缓冲区满,则将缓冲区的内容写入磁盘文件,或者flash缓冲区。close文件描述符的时候也会将数据从缓冲区写入磁盘。
5.TCP心跳包的作用##
由于系统keeplive参数的默认设置情况下的短线检测时间是7200秒,时间非常的长,这对于实时通讯要求比较高的连接来说是很不合适的,所以需要我们自己设定心跳的时间等参数。
6.说一下boos中share_ptr和scoped_ptr的区别##
- shared_ptr可以有多个指针指向同一个地址来享有共享权,内部包含一个引用计数,当这个指向这个地址的share_ptr全部都离开作用域时,会清空引用计数,并回收这段内存。
- scoped_ptr只能是独享共有权,当发生复制和拷贝时,原来的scoped_ptr将失去使用权。(但是可用reset函数重置指向的对象,或者用swap函数交换指针所指的对象)
7.TCP中,如果client一直发送数据,并且server端接收的非常慢,会对双方产生什么样的后果##
会发生阻塞的情况,不会发生丢包的情况,因为TCP在丢包时会重发,知道对方接收到。
8.TCP的粘包和拆包##
情景如下,假设client需要发送数据包D1和D2,以下情况会出现粘包和拆包的现象:
- server刚好分两次接收到了D1和D2,没有发生粘包和拆包
- server一次就将D1和D2接收完,D1和D2粘在一次(粘包)
- server第一次接收到D1的一部分,第二次才读取D1的剩余内容和D2(拆包)
- server滑动窗口非常小,需要很多次才将D1和D2接受完(多次拆包)
9.如何解决粘包和拆包的问题##
由于TCP底层无法理解应用层是否发生了数据的粘包和拆包,所以需要我们设计应用层,将粘包和拆包现象的数据重新解析为正确的数据,解决办法如下:
- 消息定长,如每个报文的长度固定200字节,不足的用空格补齐(可能导致无用数据占用网络)
- 在包尾增加回车换行符进行分割;
- 将消息分为消息头和消息体,消息头包含消息体长度的字段,通常的处理方法是消息头的第一个字段用int来表示消息的长度;
- 设计更复杂的消息层协议。
10.如果只有头文件(甚至没有)和dll文件,没有lib文件,怎么使用这个动态库##
如果只有头文件和dll,可以采用LoadLibrary();GetProcAddress();FreeLibrary();
HINSTANCE hDLL; // DLL句柄知
typedef int (*DLLFUN)(int a, int b);
DLLFUN Dll_clFun;
//读取:
if(hDLL == NULL)
hDLL=LoadLibrary((LPCTSTR)"TestDLL.dll");
if(hDLL)
{
Dll_clFun =(DLLFUN)GetProcAddress(hDLL,"clFun");//函数名
}
//释放回:答
if(hDLL)
{
FreeLibrary(hDLL); // 卸下DLL
hDLL = NULL;
}
如果只有dll,连头文件都没有
如果是简单的函数,参数列表很少,返回值很简单,那么可以用depends工具来查看函数名,在用逆向工具通过汇编得到参数和返回值,最后再用以上的方法来调用dll
如果函数很复杂,目前我也不知道怎么办,反汇编?
11.说一下动态库的加载过程##
搜不到,不知道
12.字节序,大小端##
大端:高位字节存放在低地址
小端:低位字节存放在低地址
x86平台下默认是小端序,而网络传输协议采用大端序,不同平台下的字节序需要转换才能使用
13.如何判断大小端##
- 用指针,用char型指针去读int型指针的高位地址,判断高位地址的实际值,从而判断大小端(还可以用联合体)
bool isLittleEndian()
{
unsigned int i = 0x12345678;
unsigned char* c = (unsigned char*)&i;
return(*c == 0x78); //判断是否是低位字节存内存低地址 *c取得就是内存中存放i的低地址
}
- 库函数,htonl(Linux下),(1 != htonl(1));真小端,假大端
14.QT窗口如何重绘##
添加一个类继承Qdialog,然后重写paintEvent函数,update()函数可以刷新窗口;
还可以重写其他的事件函数
15.qt中qss的使用##
qss是qt的样式表,可以存储在文件中filename.qss,使用时通过读文件到QString中,然后在初始化时调用setStyleSheet函数,将样式表运用到界面中来。具体的用法还没来得及看,内容比较多
16.说一下窗口的创建过程##
MFC应用程序创建窗口的过程
-
1.PreCreateWindow() 该函数是一个重载函数,在窗口被创建前,可以在该重载函数中改变创建参数(可以设置窗口风格等等)
-
2.PreSubclassWindow() 这也是一个重载函数,允许首先子分类一个窗口
-
3.OnGetMinMaxInfo() 该函数为消息响应函数,响应的是WM_GETMINMAXINFO消息,允许设置窗口的最大或者最小尺寸
-
4.OnNcCreate() 该函数也是一个消息响应函数,响应WM_NCCREATE消息,发送消息以告诉窗口的客户区即将被创建
-
5.OnNcCalcSize() 该函数也是消息响应函数,响应WM_NCCALCSIZE消息,作用是允许改变窗口客户区大小
-
6.OnCreate() 该函数也是一个消息响应函数,响应WM_CREATE消息,发送消息告诉一个窗口已经被创建
-
7.OnSize() 该函数也是一个消息响应函数,响应WM_SIZE消息,发送该消息以告诉该窗口大小已经发生变化
-
8.OnMove() 消息响应函数,响应WM_MOVE消息,发送此消息说明窗口在移动
-
9.OnChildNotify() 该函数为重载函数,作为部分消息映射被调用,告诉父窗口即将被告知一个窗口刚刚被创建
https://www.cnblogs.com/findumars/p/5870464.html
QT应用程序创建窗口的过程
https://www.cnblogs.com/findumars/p/4700251.html
17.qt中moc的理解##
moc 全称是 Meta-Object Compiler,也就是“元对象编译器”。QT在编译源代码之前,会用moc先分析C++源文件,如果这个C++文件包含Q_OBJECT,那么他会生成另外一个CPP文件,文件名以moc_开头,如moc_test.cpp,然后这个新的CPP文件会一起进入编译系统,最终被链接到二进制代码中。moc在预处理之前,会展开宏Q_OBJECT的内容。
QT并不是一种编程语言,他还是基于C++的编译器的,只不过在编译之前会通过MOC来预先处理CPP文件,将QT框架下的特性如信号和槽加入到CPP中,最终通过C++的编译器来生成可执行程序。
18.说说信号和槽##
https://blog.csdn.net/hyongilfmmm/article/details/83015045