当前位置: 首页>编程语言>正文

2024最新大厂C++校招面试真题合集,大厂面试百日冲刺 bay13

火烈鸟网络C++开发

空类对象的大小?

C++中空类的对象大小为1字节

——————————————————————————————————

哪些函数不能为虚函数?

构造函数静态成员函数内联函数友元函数

——————————————————————————————————

含有虚函数的空类对象大小?

含有虚函数的空类对象大小通常为一个指针的大小,在32位系统上通常是4字节,在64位系统上通常是8字节。

——————————————————————————————————

模板类可以不可以继承?

可以继承

——————————————————————————————————

new和malloc的区别?

new 在分配内存时自动计算所需大小,并返回正确的类型指针,无需进行类型转换;而 malloc 需要手动计算字节数,并返回 void* 类型,使用时通常需要强制类型转换。

new 会调用对象的构造函数初始化对象,并且与之对应的 delete 会调用析构函数;malloc 只负责分配内存,不调用构造函数,与之对应的 free 也不调用析构函数。

当内存分配失败时,new 会抛出 bad_alloc 异常(除非使用了 nothrow 版本),而 malloc 会返回 nullptr

new/delete 是C++中的操作符,malloc/free 是C语言中的库函数。

——————————————————————————————————

模板能否偏特化?

可以偏特化

——————————————————————————————————

vector如何工作的?底层介绍下

  1. 内存分配:当你创建一个 vector 时,它会预分配一定量的内存。这个量通常是其容量(capacity),即在需要重新分配之前 vector 可以保存的元素数量。
  2. 自动扩容:当新元素被添加到 vector 并且当前容量不足以容纳它时,vector 会自动扩大其内存空间。通常,这是通过分配一个更大的内存块,复制现有元素,然后释放旧内存来实现的。
  3. 元素访问vector 提供了像 operator[] 这样的访问操作符来进行快速索引访问,因为其数据是连续存储的。
  4. 元素添加:元素可以通过 push_backemplace_back 方法添加到 vector 的末尾。如果有必要,这些操作还会触发自动扩容。
  5. 内存管理vector 会自动管理其内存的生命周期。当对象被销毁时,分配的内存会被释放。使用 reserve 方法可以显式增加容量,而 shrink_to_fit 方法可以请求减少未使用的容量。

——————————————————————————————————

queue队列怎么清空元素?

要清空 std::queue 容器中的所有元素,可以使用 while 循环调用 pop() 方法,直到队列为空。

——————————————————————————————————

C++11新特性有哪些异步操作?

  1. std::async:一种启动异步任务并返回 std::future,用于稍后获取任务的结果的机制。
  2. std::future:表示异步操作结果的类,提供了获取计算结果的方法。
  3. std::promise:一种可以从线程中设置值的机制,其值可以通过关联的 std::future 对象来获取。
  4. std::packaged_task:将一个函数或可调用对象包装为一个异步操作,这个操作的结果或异常存储在 std::future 对象中。

——————————————————————————————————

智能指针怎么做到内存管理的?

智能指针通过封装原始指针,并自动管理其生命周期来实现内存管理。当智能指针的实例被销毁(例如,超出作用域或被显式删除)时,它会自动释放其管理的原始指针所指向的内存。

——————————————————————————————————

一个业务,客户端的异步请求,怎么变为同步操作?

将一个异步请求转换为同步操作可以通过使用std::futurestd::async来实现。

  1. 使用std::async启动异步任务std::async启动一个异步任务,并返回一个std::future对象,该对象在未来某个时点可以用来获取异步任务的结果。
  2. 通过std::future::get方法等待异步任务完成并获取结果std::future::get会阻塞调用线程,直到异步任务完成,并返回任务的结果。此时,原本的异步操作就转换为了一个同步操作,因为调用者必须等待异步任务完成才能继续执行。

——————————————————————————————————

单链表怎么找到中间节点?

使用快慢指针算法

  1. 初始化两个指针,slowfast,都指向链表的头节点。
  2. 移动这两个指针,slow 每次向前移动一个节点,fast 每次向前移动两个节点。
  3. fast 到达链表末尾或者 fast 的下一个节点为空时(这取决于链表的长度是奇数还是偶数),停止移动。此时 slow 指针指向的就是链表的中间节点。

——————————————————————————————————

设计一个定时器链表每次都要遍历怎么优化?追问我为什么?

不需要遍历整个链表,只需要遍历到前面的超时部分。因为链表中这个点之后的所有定时器都设置为在未来超时,因此它们现在不需要被处理。这样可以减少不必要的遍历,提高效率。

——————————————————————————————————

IO多路复用除了网络还有哪些用途?

  1. 监控多个文件描述符的事件,包括管道和串口。
  2. 同时管理用户输入和文件读写操作。
  3. 实现基于事件驱动的服务器,如数据库和Web服务器。
  4. 在进程间通信中同步或传输数据。
  5. 监听操作系统内核发出的各类信号。

——————————————————————————————————

如何解决频繁分配对象导致的内存碎片问题?

  1. 使用内存池:预分配一大块内存,然后从这个内存池中分配小片内存给对象使用,可以减少系统的内存分配次数,从而减少内存碎片。
  2. 对象缓存:重用已经分配但不再使用的对象,而不是频繁创建和销毁。
  3. 定制分配器:为特定的对象创建定制的内存分配器,优化内存分配和回收策略,减少碎片产生。
  4. **块分配:对于需要频繁创建和销毁的小对象,采用块分配策略,即一次性分配一大块内存,然后在这上面分配小对象。
  5. 智能指针:虽然它们主要用于管理对象生命周期和避免内存泄漏,但配合对象缓存等技术使用,也可以减少频繁分配和销毁对象,间接减少内存碎片问题。

——————————————————————————————————

tcp发送数据包内核经过了几次拷贝?

在TCP发送数据时,一般情况下,内核会进行两次拷贝操作:第一次从用户空间拷贝到内核空间的缓冲区,第二次从内核空间的缓冲区拷贝到网络接口的发送缓冲区。这就是所谓的"双拷贝"。

——————————————————————————————————

udp如何做到可靠传输?

UDP本身不提供可靠传输,但可以通过在应用层实现以下机制来增加其可靠性:

  1. 确认和重传:发送方维护未被确认的数据包列表,接收方收到数据后发送确认(ACK)。未收到ACK的包将被重发。
  2. 序列号:每个数据包都分配一个序列号,以便接收方检测丢失或重复的包。
  3. 校验和:数据包包含校验和,以检测在传输过程中的数据损坏。
  4. 超时重传:发送方设置超时计时器,如果在指定时间内未收到确认,重新发送数据包。
  5. 流量控制:避免发送方过快发送数据包,导致接收方处理不过来。
  6. 拥塞控制:根据网络状况调整数据发送速率,避免过多数据包导致网络拥塞。


https://www.xamrdz.com/lan/5qt1962481.html

相关文章: