2023年04月13日 9:30:00
这个面试好像比较着急,也没有自我介绍,面试官直接就问问题了。

一共面了40min左右

介绍一下epoll是什么?

epoll和select有什么区别?

  1. 效率不同: 在处理大量文件描述符的情况下,epollselect 更快更高效。这是因为 epoll 使用了红黑树(或者哈希表),能够快速检索就绪的文件描述符,而 select 只是简单地轮询所有的文件描述符。
  2. API 使用方式不同: epoll 使用更加简洁明了的 API,只需要调用 epoll_create() 创建 epoll 实例,然后使用 epoll_ctl() 向其注册事件和监听的文件描述符,最后使用 epoll_wait() 等待就绪的文件描述符即可。而 select 需要使用 fd_set 结构体进行操作,需要编写较为复杂的代码。
  3. 支持的最大文件描述符数不同: select 在不同平台上支持的最大文件描述符数不同,一般情况下为 1024 左右,而 epoll 可以支持非常大的文件描述符数量,受系统资源限制。

综上所述,epoll 是更为高效和灵活的 I/O 多路复用机制,在高并发场景下更受欢迎。

select和epoll都是能在linux上用吗?

是的

说一下状态机是什么,有什么优点,以及它在HTTP请求的解析里面有什么用?

这个没准备清楚,没答上来

状态机被广泛应用于描述程序或协议的行为,以及对输入的响应。

状态机的主要优点是:

  1. 易于理解和描述:状态机描述了系统的状态和转移行为,可以用图形化的方式表示,便于理解和描述系统的行为。
  2. 易于实现和调试:状态机可以直接转化为代码实现,通过调试器可以很方便地调试和测试。
  3. 易于扩展和维护:当系统需要增加新的状态或转移时,可以直接在状态机中添加新的状态或转移,而不会影响原有的代码和逻辑

在 HTTP 请求的解析中,状态机被广泛地使用。HTTP 请求的解析过程是一个典型的输入有序、处理有序的过程,其中每个步骤都是在特定的输入状态下进行的。

从状态机即parse_line函数,负责读取http报文的第一行,检查读到的一行是否合法,

若合法,则从状态机状态返回LINE_OK,主状态机即parse_request_line函数解析请求行,完成后的状态为CHECK_STATE_REQUESTLINE表示要检查

然后从状态机继续从报文中读取一行,若状态变为LINE_OK,触发主状态机进行解析请求头(parse_headers函数),如果是get请求,就执行请求函数,如果是post解析后状态变为CHECK_STATE_CONTENT表示要检查http的消息体,这就又需要从状态机读取数据,当状态变为LINE_OK时,则可以执行post请求了

知道那个网络通讯中粘包的情况吗?要如何解决呢?

我:一个数据分成多个包连续发包的时候,无法确定包结束。方法有加结尾标识符和TCP包上加packet len

C++中虚函数是什么,它的机制是什么?

没准备清楚

C++中虚函数是一种特殊的成员函数,它允许在基类和派生类使用同名的函数,实现了多态的特性。虚函数是C++中实现多态(运行时多态)的一种方式。

当基类中的成员函数被声明为虚函数时即函数声明前加上virtual,派生类可以重写该函数,使用基类指针(引用)指向派生类对象,在运行时,调用该函数时会根据对象的实际类型调用相应的函数。这样就实现了运行时的多态性。

虚函数的机制是通过虚函数表 vftable虚函数指针 vfptr 来实现的。每个对象都有一个指向其虚函数表的指针(即虚函数指针),虚函数表是一个数组,包含了该类中所有的虚函数及其地址,最开头是RTTI指针,标识当前对象的实际类型vfptr 存放在类的内存空间的最前面。派生类中的虚函数表会继承基类中的虚函数表,如果派生类中重写了基类中的虚函数,就会在派生类的虚函数表中更新该虚函数的地址。当调用虚函数时,通过对象的虚函数指针找到对应的虚函数表,再根据虚函数在虚函数表中的位置找到实际需要调用的函数即vfptr->vftable->func()

一个类里虚函数个数,不影响类大小(都只是存一个vfptr),影响的只是虚函数表大小

一个类只有一张虚函数表

虚函数表是存在哪里的?

进程虚拟地址空间的.rodata 只读数据

二义性怎么解决?

这个问题没听懂,应该要问一下面试官的

https://blog.csdn.net/afei__/article/details/82141731

https://blog.csdn.net/wangjian530/article/details/80469625

在C++中,二义性(Ambiguity)指的是在继承关系中出现了歧义,即在调用成员函数时无法确定应该使用哪一个版本的函数。例如,假设有一个基类A和两个派生类B和C,B和C都重载了一个函数foo,如果在另一个类D中以B和C的对象作为参数来调用foo函数,编译器将无法确定应该使用哪一个版本的foo函数,这就是二义性。

class A{public:void f();
}class B{public:void f();void g();
}class C:public A,public B{public:void g();void h();
}
// 另一种二义性,菱形继承
class A
{public:int a; // B1,B2 都将继承一个变量 a
};
class B1 : public A
{};
class B2 : public A
{};
class C : public B1, public B2
{};int main()
{C c;c.a = 10; // ERROR ! 二义性 !!!return 0;
}

如果声明:C c1,则c1.f();具有二义性,而c1.g();无二义性(同名覆盖)

为了解决二义性问题,C++提供了以下几种解决方案:

  1. 使用作用域限定符:使用作用域限定符可以明确指定需要调用的函数版本。例如,可以使用类名限定符来调用基类中的函数,或者使用派生类名限定符来调用派生类中的函数。

    int main()
    {C c;c.A::f();c.B::f();return 0;
    }
    
  2. 使用虚函数:在基类中定义虚函数,让派生类重写虚函数,通过动态绑定来调用正确的函数版本。

  3. 使用virtual继承:如果派生类从多个基类继承,而这些基类中有共同的基类,那么可以使用virtual继承来避免共同基类的重复继承。

  4. 使用强制类型转换:使用强制类型转换可以将对象转换为需要的类型,以调用指定的函数版本。但是这种方式不是推荐的做法,因为可能会造成代码可读性下降和运行时错误。

C++中拷贝构造函数和拷贝赋值函数什么时候用到?

拷贝构造使用场景

拷贝构造函数用于创建一个新对象,该对象是已有对象的副本。通常,拷贝构造函数采用另一个同类型的对象作为参数,并从该对象中复制数据。拷贝构造函数可以在以下情况下使用:

  • 初始化一个对象,将其作为参数传递给函数或返回一个对象时;
  • 通过另一个对象进行初始化或赋值。

拷贝赋值函数使用场景

拷贝赋值函数用于将一个对象的值赋给另一个对象。拷贝赋值函数采用另一个同类型的对象作为参数,并从该对象中复制数据。左边的对象已经初始化过!

知道深浅拷贝吗?什么时候要深拷贝什么时候要浅拷贝?

  • 浅拷贝:只复制指针,不复制指针所指向的内容。
  • 深拷贝:复制指针所指向的内容,即重新分配一块新的内存,将原指针所指向的数据拷贝到新的内存空间中。
  • 当类中的成员变量指向动态分配的内存时,进行对象拷贝操作时需要使用深拷贝,以确保新的对象与原始对象完全独立,对一个对象的修改不会影响另一个对象,并且防止二次析构的问题。
  • 当类中的成员变量不指向动态分配的内存时,进行对象拷贝操作时可以使用浅拷贝。这是因为在这种情况下,复制指针并不会对程序产生任何负面影响。

RTTI是什么?

RTTI是C++中的一种运行时类型识别机制,它允许程序在运行时查询一个对象的实际类型信息。RTTI主要用于多态场景中,例如,当一个基类指针指向一个派生类对象时,通过RTTI可以判断出该指针所指向的对象的实际类型。

可以通过使用两个关键字typeiddynamic_cast来实现RTTI:

typeid关键字:用于查询一个对象的类型信息

dynamic_cast运算符:用于将一个基类指针或引用转换为派生类指针或引用,如果转换失败则返回nullptr

虚函数表中起始部分存放RTTI指针标识动态类型,从而能实现多态;

RTTI是一种运行时机制,需要在程序运行时才能进行类型信息的查询和转换。由于这种机制会增加程序的运行时开销。使用虚函数实现多态,而不是手动进行类型转换是一种避免额外RTTI开销的方法。

内存泄漏这种问题有了解过吗?怎么去防范?

内存泄漏是指在程序运行时,分配的内存空间没有被及时释放(malloc-free, new -delete),导致程序占用的内存越来越多,最终导致程序崩溃或性能下降等问题。

下面是一些防范内存泄漏的方法:

  1. 分配内存时,要确保在不需要使用该内存时及时释放。例如,对于动态分配的内存空间,使用deletedelete[]进行释放。
  2. 注意对象生命周期的管理。在对象不再使用时,应该及时销毁。如果对象被其他对象引用,应该在没有任何引用时再进行销毁。比如在delete之前抛出异常或者return
  3. 对于资源对象,应该使用RAII(Resource Acquisition Is Initialization)技术进行管理。RAII是一种通过在对象的构造函数中获得资源,在析构函数中释放资源的技术,可以避免手动管理资源带来的错误。
  4. 尽量避免使用裸指针进行内存管理,使用标准库中的智能指针或其他封装良好的类库进行内存管理。
  5. 在编写代码时,可以使用内存泄漏检测工具(如Valgrind、ASAN等)对代码进行检测,及时发现内存泄漏问题。

rpc工作原理是什么,介绍一下?

不知道,还没深入学

RPC(Remote Procedure Call,远程过程调用)是一种分布式计算模型,它允许程序在不同的计算机之间通过网络进行通信和交互,实现像本地调用一样的程序调用和数据传输。RPC通常用于构建分布式系统和微服务架构。

RPC的工作原理可以简单地分为以下几个步骤:

  1. 客户端调用远程服务:客户端程序调用本地接口,接口封装了需要执行的操作和参数,然后将请求通过网络发送到远程服务端。
  2. 服务端接收请求:远程服务端接收请求,解析请求的内容,根据请求的操作调用相应的方法,执行操作。
  3. 服务端返回结果:服务端将执行结果返回给客户端,客户端接收到结果后继续执行。
  4. 客户端接收结果:客户端接收到服务端返回的结果,进行处理并返回给调用者。

在这个过程中,RPC通常需要解决以下问题:

  1. 远程服务的定位:客户端需要知道远程服务的位置和地址,才能将请求发送到正确的服务端。解决这个问题可以使用命名服务(如DNS)、注册中心等技术。
  2. 数据传输和序列化:客户端和服务端之间需要进行数据传输和序列化。RPC框架通常使用网络协议(如HTTP、TCP等)进行数据传输,同时需要将数据序列化成二进制流或其他格式(Protobuf, json)。
  3. 异常处理容错机制:由于网络和远程服务的不确定性,RPC框架需要提供异常处理和容错机制,例如超时重试、故障转移等技术,保证RPC调用的可靠性和稳定性。

回溯算法是什么?什么情况下使用

回溯算法(Backtracking)是一种暴力搜索算法,用于在所有可能的情况下寻找解决方案。它通过尝试所有可能的解决方案,并在找到满足条件的解决方案后,回溯到之前的状态,继续搜索,直到找到所有可能的解决方案或确定无解。因此,回溯算法通常用于求解组合排列、集合划分、子集、排列组合和图等问题。

一道手写算法题,求数组中目标和返回下标,要求时间复杂度为O(n)就是用回溯解决

一个英语问题:can you tell me about your education and work experiences?

到这里已经紧张到爆炸了,节奏全乱了。

I studied Telecommunication Engineering at Zhejiang University City College for my undergraduate degree and I am currently pursuing my second-year Master’s degree in Computer Science at Yunnan University of Finance and Economics. My area of interest in the field is C++ development, and I gained experience in this area last summer through an internship where I worked on C++ QT development at a company. Through this experience, I learned about relevant software development processes and improved my abilities in reading code and communicating with others

反思

感觉讲话还是要多练习一下。。和面试官讲话一对比,还是紧张太多了。没有聊天的感觉,而是审判的感觉~~还是要聊起来。

有不懂的可以和面试官问一下,一场给自己三次问的机会吧

下一次面试,一定要缓和心态,先不要说别的,冷静下来啊!感觉节奏很糟糕。就好像唱错一个音后面就全乱了。

不要人家一问就急着回答!!!!!

联想C++实习面试凉经相关推荐

  1. 透彻解析!字节跳动Android实习面试凉凉经,年薪超过80万!

    什么是Kotlin? Kotlin,如前面所说,它是JetBrains开发的基于JVM的语言.JetBrains因为创造了一个强大的Java开发IDE被大家所熟知.Android Studio,官方的 ...

  2. 字节跳动Java实习面试凉凉经,附答案+考点

    写在前面 很多小伙伴留言说让我写一些工作过程中的真实案例,写些啥呢?想来想去,写一篇我在以前公司从零开始到用户超千万的数据库架构升级演变的过程吧. 本文记录了我之前初到一家创业公司,从零开始到用户超千 ...

  3. 字节跳动Android实习面试凉凉经,震撼来袭免费下载!

    开头 最近,程序员这个圈子可谓热闹非凡,前不久,一个神奇的开源项目996.ICU诞生,几天时间就有超过10w+ star 和 1w+ fork ,可谓是Github上star增长最快的项目.996.i ...

  4. 泪目!字节跳动Android实习面试凉凉经,面试必备

    前言 最近我开始偷偷投简历了.与老东家的合同快要到期,想知道自己的斤两,续签合同也好有个底,顺便悄悄看看新的工作机会.虽然市场环境不好,但我们身在涨工资靠跳槽的行业没办法. 由于工作了5年了,经验有了 ...

  5. 四面阿里Java开发岗,字节跳动Java实习面试凉凉经

    开头 我们面试的时候 ,经常会被问这种到问题:Spring中bean的循环依赖怎么解决? Spring中bean的加载过程? spring相关的问题一直是大厂面试常问到的一个问题,也是一直困扰这我们, ...

  6. 字节跳动Android实习面试凉凉经,面试总结

    开头 通常作为一个Android APP开发者,我们并不关心Android的源代码实现,不过随着Android开发者越来越多,企业在筛选Android程序员时越来越看中一个程序员对于Android底层 ...

  7. 安卓音视频开发,字节跳动Android实习面试凉凉经,年薪超过80万!

    前言 前几天去参加了一场面试.面试的题目大多很基础,有一道关于埋点的问题,面试官问我如果不用第三方SDK进行埋点,自己埋点的话,如何减少埋点对业务代码的入侵. 当时没想太多,就说创建一个 BaseVi ...

  8. 打不死的小强(找实习面试篇)

    理工男不善长写文章,看到别人分享自传,觉得有趣.自己也分享一下自己的渣渣经历.为了避免过于臃肿,本篇仅分享关于找实习面试的经历. 首先申明,本人只是一个渣渣程序员,并不是什么大神,大神请忽略本篇. 说 ...

  9. Java实习面试重点基础知识

    今天第一次参加面试,十分紧张,加上本身我就学艺不精,没系统学过Java去面Java实习,问出的许多问题我都没有回答出来,估计我的第一次实习生面试凉了. 不过总不能沉溺于过去,总结一下今天面试中我遇到的 ...

最新文章

  1. 百度搜索效果(页面传来数据地址,由服务器去获取)
  2. linux内核网络协议栈--ip层报文转发之ip_local_out()函数(六)
  3. uva 12100 Printer Queue 优先级队列模拟题 数组模拟队列
  4. 微信公众帐号开发教程第6篇-消息及消息处理工具的封装
  5. 通过Service访问应用 (2)
  6. web加载本地html,WKWebview加载本地html问题汇总
  7. 区块链未来发展三大关键词,华为云如何见招拆招?
  8. c语言不允许有常量的是,C语言试卷第10套含答案.doc-资源下载人人文库网
  9. SQL SERVER 事务例子
  10. POJ 3671 DP or 乱搞
  11. google黑客命令搜集
  12. matlab乘方报错,Matlab精炼语法
  13. Mathtype(2),用于创建此对象的程序是 Equation。您的计算机尚未安装此程序或此程序无响应。
  14. collect2: error: ld returned 1 exit status(Linux下Gcc编译问题)
  15. 《Linux就是这种范儿》读后感
  16. ubuntu清空回收站命令
  17. 姓名转拼音的几种格式
  18. python小于100的所有合数,python输出100以内的质数与合数
  19. GRBL四:GRBL框架解析
  20. 虚拟空间+AI设计是锦上添花吗?|​聊聊虚拟空间设计

热门文章

  1. DB2 UDB V8.1 管理 学习笔记
  2. 数值计算——牛顿插值法
  3. t3系统总显示得不到服务器,用友T3不能连接服务器你好,用友T3总是说连接不到服务...
  4. BasicSRSuper-resolution——Video2video
  5. Jetson-Nano系统克隆
  6. Web矢量图设计器的应用场景
  7. 开篇词:千万不要心存侥幸
  8. eCalc:最棒的在线计算器
  9. 总结了 11 种 Numpy 的高级操作!
  10. 【已解决】AC86U ML改版固件虚拟内存创建失败,提示USB磁盘读写速度不满足要求