您的位置:首页 > 编程语言 > C语言/C++

2020腾讯C++后台开发暑期实习电话面(一)

2020-04-07 12:14 1666 查看

腾讯暑假C++后台开发实习电话一面

2020年3月24日晚上8点接到了腾讯的电话面试。主要是关于基础知识和项目经历的询问。
一、自我介绍
XXXXXXX。

二、介绍项目
XXXXXXX。

三、C++基础
1、说一下函数的重载、覆盖与隐藏
答:重载指的是同一可访问区间内被声明的几个具有不同参数列表的同名函数,根据参数列表确定调用哪个函数,与函数的返回类型无关。
重写指的是子类中存在重新定义的函数。其函数名,参数列表,返回值类型必须和被重写的函数一致。只有函数体,也就是函数花括号内的内容不同。子类调用函数时,会调用已重写的函数,不会调用父类中被重写的函数。基类中的被重写函数必须有virtual修饰。
隐藏指的是子类中函数屏蔽了其父类函数,只要派生类中函数名与基类中函数名相同,就会被隐藏。隐藏方法无法实现多态。
重载和覆盖的区别:
范围不同:覆盖与被覆盖的函数在不同的类中,一般为父类和子类;重载和被重载函数在同一个类中。
参数不同:覆盖与被覆盖的函数参数列表一定相同,重载和被重载的函数列表一定不同。
virtual区别:覆盖的父类函数必须被virtual修饰,重载函数与被重载函数可以被virtual修饰,也可以不被virtual修饰。

2、说一下程序在内存中的分布,在哪几个区?哪些区是被编译器分配的,哪些区是人工分配的。
答:一般情况下,数据在内存中分为四个区。第一个区是栈区,主要由编译器分配内存;第二个区为堆区,主要是程序员进行分配;第三个区是全局数据区,用来存储全局变量。第四个是代码区,主要是存储代码的。

3、STL中的vector、list、map的底层原理。
答:vector与数组类似,内存分配在一整块内存,不同的地方在于vector能够动态的调整存储空间的大小,数组只能是静态的调整大小。注:vector动态的调整大小并不是在原有空间的后面加上一块空间,而是以原来大小的两倍在内存的其他地方进行分配,然后将原来的内容拷贝过来,再在原内容之后构造新元素,因此,一旦引起空间重新配置,原来指向vector的迭代器都失效了。
list是数据结构中的双向链表,内存空间不连续,通过指针进行数据的访问,随机存储非常没有效率,三是删除和插入比较有效率。
map是关联容器,以键值对的形式进行存储,方便进行查找,关键词起到索引作用,值则表示与索引相关联的数据,以红黑树的结构实现,插入和删除操作都可以在O(log⁡n)O(\log{n})O(logn)时间内完成。

4、指针和引用的区别,谁更安全,为什么?
答:指针是一个变量,只不过这个变量存储的是一个地址,指向内存的一个存储单元;而引用仅是个别名。引用更安全,因为引用不涉及对地址的操作。
PS:
(a)(a)(a)引用不可以为空,当被创建的时候,必须初始化,不能为NULL值;而指针可以为空值,可以在任何时候初始化。
(b)(b)(b)有const指针,但是没有const引用。
(c)(c)(c)指针可以有多级,但引用只能有一级。

int **p;

(d)(d)(d)指针的值在初始化后可以改变,而引用的值在初始化后不可改变。
(e)(e)(e)sizeof()函数作用引用的时候,返回值是变量的大小;sizeof()函数作用指针的时候,返回值是指针的大小。
(f)(f)(f)如果返回动态内存的对象或者内存,必须使用指针,使用引用可能引起内存泄露。

四、计算机网络
1、TCP为什么采用三次握手,两次握手行不行?为什么不行?
答:如果客户端发出的第一个连接请求报文并没有丢失,而是滞留在某个网络节点,以致延误到连接释放以后的某个时间才到达服务器端。本来是一个早已失效的报文段,但是服务器认为客户端要建立连接,于是向客户端发送确认报文段,也就是第二次握手,而客户端现在不需要连接服务器,则对确认报文不予理睬。服务器认为客户端已经确认,所以开始传送数据,而客户端不接受数据,至此会导致大量占用网络资源。所以二次握手不行。三次握手可以很好的解决这个问题,如果服务器收不到客户端发送过来的第三次握手,也就是客户端对服务器确认报文的确认,则不会给客户端发送数据,也就不会造成网络资源的浪费。

2、网络编程中的socket相关内容。
答:套接字是网络编程中的一种通信机制,是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。
其中的bind()函数,把本地的协议地址赋予一个套接字;listen()函数是一个被动的套接字,指示内核将客户端发送的connect()函数连接传送给listen();connect()函数是客户端连接服务器的一种方式。
补充点:send(SOCKET s,const char FAR *buf,int len,int flags)函数,send()函数中的第一个参数是发送端的套接字描述符,第二个参数是要发送的数据缓冲区,第三个参数指实际要发送的数据字节数,第四个标志flags通常置1;在同步Socket的大致流程如下:先将要发送的实际数据长度len与buf的长度进行比较,当len小于buf长度时,在将len与buf中的剩余空间进行比较,若大于剩余空间的长度则等待协议将buf中待发送或者已发送的数据通过协议发送完毕,若小于buf中的剩余空间长度则将实际要发送的数据copy到buf剩余空间中,等待协议将数据发送给TCP的另一端。TCP的另一端使用recv(SOCKET s,char FAR *buf,int len,int flags)函数接受数据,第一个参数是接受端的套接字描述符,第二参数buf是接收端的数据缓冲区,第三个是缓冲区的大小,第四个标志位通常置为0;在等待套接字s接受发送端的数据完毕后,将s缓冲区中的数据copy到buf缓冲区中,如果数据过大可能要多调用几次recv()函数。send()函数和recv()函数在以上过程中出现错误会返回SOCKET ERROR。(以下图片为网图,仅做参考)

3、介绍网络编程中的select、poll、epoll区别和联系。
答:select、poll、epoll是指IO高复用中的三个模型,即如何在单个进程中完成频繁数据的输入和输出,比如在服务器中服务100万个socket连接。

select的实现方法:用户调用select函数,询问内核态中的数据是否准备好,如果准备好则返回给用户可读条件,同时用户这边系统受阻于select的调用,等待多个文件描述符中任意一个返回,则读取文件句柄,指示内核态拷贝数据,等待内核态拷贝数据完成返回成功指示后,再处理数据包。(网图,仅供参考)

select缺点:1、单个进程监控的文件描述符有限,通常为1024*8个文件描述符,select采用轮询方式扫描文件描述符,文件描述符越多则性能越差。
2、内核态到用户态数据拷贝频繁,操作复杂。
3、轮回时间效率低,select返回的是整个数组的句柄,应用程序需要遍历整个数组材质带谁发生了变化。
4、select是水平触发,应用程序如果没有完成对一个已经就绪的文件描述符进行操作,则select之后还会返回给进程。

poll模型与select类似,不过是采用链表进行存储的。优于select是没有文件操作数目上限。

epoll模型:epoll通过在linux申请一个建议的文件系统,把select调用分为了三个部分。
1、调用epoll_create建立一个epoll对象,这个对象包括有个红黑树和一个双向链表。并与底层建立回调机制。
2、调用epoll_ctl向epoll对象中添加这100万个连接的套接字
3、调用epoll_wait收集发生时间的连接。
epoll比select/poll的优越之处:因为后者每次调用时都要传递你所要监控的所有socket给select/poll系统调用,这意味着需要将用户态的socket列表copy到内核态,如果以万计的句柄会导致每次都要copy几十几百KB的内存到内核态,非常低效。而我们调用epoll_wait时就相当于以往调用select/poll,但是这时却不用传递socket句柄给内核,因为内核已经在epoll_ctl中拿到了要监控的句柄列表。
红黑树结构如下:

整体:

五、Linux系统
1、查看端口号
答:nestat -tunlp | grep XXX

2、查看磁盘
答:df -l

3、查看CPU
答:没回答出来,查了百度,top vsmtat dstat。

六、有什么想问的
答:我自己有什么不足的地方。
答:知识掌握的深度和广度不够,TCP编程需要加强。

  • 点赞 6
  • 收藏
  • 分享
  • 文章举报
知愚 发布了5 篇原创文章 · 获赞 7 · 访问量 1214 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: