CVTE一面(C/C++研发):2017-08-09

2017-08-16 00:25 阅读 1,052 次 评论 0 条

私有继承是is-a还是has-a关系?

is-a,属于接口继承,继承关系均为is-a的关系,与继承的方式无关,只有组合才是has-a关系,是一种实现继承。如下所示:

了解迭代器失效吗?如何解决?

迭代器失效分三种情况考虑,分别是数组型、链表型、树型数据结构。

数组型数据结构:也就是vector迭代器的原生指针,删除时迭代器会失效,因为删除一个元素相当于让后面的元素向前挪动一个位置,会覆盖掉要删除的位置,导致后面的迭代器全部失效。插入时如果vector不扩容,那么迭代器不会失效,只有在增容的时候迭代器才会失效。解决方法:将迭代器指向修改为增容后的位置。

链表型数据结构:对于list型的数据结构,使用了不连续分配的内存,删除使指向删除位置的迭代器失效,但是不会失效其他迭代器。解决方法:① erase(*iter)会返回下一个有效迭代器的值 ② erase(iter++)。注意:iter++的意思是,先指向下一个迭代器所指向的节点,再删除当前节点。

树形数据结构:使用红黑树存储数据,插入不会使得任何迭代器失效;删除使指向删除位置的迭代器失效,但是不会失效其他迭代器。解决方法:采用erase(iter++)的方式删除迭代器。

了解智能指针吗?谈谈你对shared_ptr的认识?

C++提供了4种智能指针用于对分配的内存进行自动释放,分别是auto_ptr、scope_ptr、shared_ptr、weak_ptr。其中auto_ptr在C++98标准引入,后三种在C++11标准中加入。

auto_ptr:核心思想是资源管理权的转移,即在构造对象时赋予资源管理权,析构对象时撤销管理权,但是auto_ptr尽量在任何情况下都不要使用,资源管理权的转移带来的最重要的缺点就是安全性问题。

scoped_ptr:它的实现原理是防止对象的赋值与拷贝,即将赋值运算符的重载与拷贝构造函数私有声明。它与auto_ptr的共同之处在于scoped_ptr和auto_ptr都是利用了一个栈上的对象去管理一个堆上的对象,从而使得堆上的对象随着栈上的对象销毁时自动删除。

shared_ptr:通过引用计数来实现的共享指针,引入一个指针变量pCount来指向一块内存空间,当调用构造函数、赋值运算符的重载以及拷贝构造函数时对计数器pCount+1,只有一个指针指向这块空间时,即pCount=1时,才可以释放空间,否则引用计数pCount-1。shared_ptr的认识与分析

weak_ptr:为了解决shared_ptr带来的循环引用的问题,引入了weak_ptr这个弱引用指针,它不能单独使用,而是用来辅助shared_ptr,它会对引用计数做出特殊的处理。

STL::map[]与find的区别是什么?哪个速度更快?

map[]:将关键码作为下标去执行查找,并返回对应的值;如果不存在这个关键码,就将一个具有该关键码和值类型的默认值的项插入map。它的底层调用红黑树的insert:

find:底层调用红黑树的find,以二叉搜索树的特性来查找关键码,返回值为一个pair键值对,成功返回<iterator,true>,失败返回<iterator,false>。

二者的查询速度:operator[]在调用过程中,需要构造一次pair,在返回insert的结果时,又需要复制一遍pair,而find只需要返回时复制一遍iterator,因此就查询效率而言,find更胜一筹。

vector如何实现扩容,它在删除元素时是否释放空间?

vector的扩容原理:vector通过一个连续的数组存放元素,如果集合已满,在新增数据时,就要分配一块更大的内存,将原来的数据拷贝过来,释放之前的内存,最后插入新增的元素。不同的版本实现的扩容方式不同,SGI版本是以1.5倍扩容,PJ是以2倍扩容。

删除元素时不释放内存:原因在于vector的元素是连续存放的,其内存也是一次性分配的,如果去回收内存还得重新分配内存,并拷贝所有元素,影响性能,因此STL把释放内存的选择交给了Coder。

谈一下TCP的粘包问题,顺便说说你的HTTP项目是如何解决粘包问题的?

粘包问题是由于TCP协议是字节流协议,没有记录边界所导致的,因此需要采用相应的分包机制来维护消息与消息的边界。

当然,并不是隶属于TCP范畴都会引起粘包问题,比如:

① 如果利用tcp每此发送数据,就与对方建立连接,然后双方发送完一段数据后,就关闭连接,这样是不会导致粘包问题的,因为只有一种包结构,类似于http协议。

② 如果发送数据无结构,如文件除数,这样发送方只管发送,接收方只管接收,也不用考虑粘包问题。

而真正需要考虑粘包问题的是:

如何区分一个整包信息,通常有以下五种做法:

1)每个数据包固定长度。例如每x个字节代表一个整包信息,不足的前面补位,解码器每次读取到指定长度的字节后再进行解码。

2)通过\r\n区分消息。例如http协议,这类区分消息的方式多用于文本协议。

3)通过指定的分隔符区分整包消息。

4)通过在协议头或消息头中设置消息的长度来表示整包信息。

5)通过协议号来确定解析协议的长度,由一个唯一协议标记就可以确定一个反序列号类,从而实现区分整包。

那么http协议是否需要考虑粘包问题呢?

答案是肯定的,http是基于tcp的应用层协议,如果是你自己解析的http协议,为什么不会出现粘包呢?http协议是按行读取的,从上至下依次是:请求行、请求报头、空行和正文,在Unix下每行结尾只有换行为'\n',在Windows下每行结尾为回车换行'\n\r',在Mac下每行结尾是回车'\r'。因此为了避免因操作系统的差异化而引起的回车换行的不一致性问题,我在项目中将回车换行同一规定为'\r\n',从而避免了粘包问题。

谈谈TCP与UDP的区别?

⒈ TCP是面向连接的,UDP是无连接的。

⒉ TCP是面向无格式的字节流,UDP是面向数据报的。

⒊ TCP提供可靠交付的服务,提供TCP连接传送的数据,无差错、不丢失、不重复,并且按序到达;UDP不能保证可靠传输。

⒋ TCP需要建立连接,有诸多可靠协议,因此传输速度较慢;而UDP无须建立连接,传输效率更为迅速。

⒌ 每一个TCP连接只能是点到点的;UDP支持一对一、一对多、多对一和多对多的交互通信。

⒍ TCP首部开销为20字节;UDP的首部开销只有8字节,分组开销小。

除此之外,在socket网络编程中,也存在如下区别:

版权声明:本文著作权归原作者所有,欢迎分享本文,谢谢支持!
转载请注明:CVTE一面(C/C++研发):2017-08-09 | 术与道的分享
分类:笔经面经 标签:, , ,
1024do.com导航_术与道导航平台

发表评论


表情