面试记录-C++软件开发

昨天面试了一家公司,招的是分布式存储开发(不懂为什么会捞我),疯狂问底层的东西,我都不会,甚至在我思考后答题的时候,其中一个面试官笑了出来…感到无语,很想问你笑什么?(忍住了)

今天面试了海康,赞赞赞,面试体验非常非常的好,自信大增。下面记录一下我觉得答的不好的问题。

1. 析构函数为什么要用虚函数?

沉默了,其实最近有看深入理解C++对象模型, 但是没有思绪,真的没有…
看了网上答案,一下就理解了。

因为多态情况下,虚基指针指向派生的时候,析构函数如果不是虚函数,那么调用的就是基类的析构函数,假设你在需要在派生对象做一些数据清理工作,结果是派生对象的析构函数就不会调用。

2. 线程池有什么优点?

参考:https://blog.csdn.net/qq_40344790/article/details/131545279

1. 线程池的介绍

  • 线程池是一种线程管理的概念,它主要用于优化多线程应用程序的性能和资源利用
  • 因为在多线程中创建和销毁线程是一个开销较大的操作。
  • 线程池通过预先创建一组线程,并将任务提供给这些线程来执行,从而避免了重复创建和销毁的开销。
  • 线程池可以限制并发线程的数量,避免资源过度占用,从而更好地管理系统资源。

2. 线程池的组成

  1. 任务队列: 用于存储待执行的任务
  2. 线程池管理器: 负责创建,管理和调度线程池中的线程。
  3. 工作线程:执行任务的单位,它们会从工作队列拿任务进行执行。

3. 这个比较有意思

https://mp.weixin.qq.com/s?__biz=MzIxNjA5ODQ0OQ==&mid=2654703373&idx=1&sn=374264396f46032f50d19ab82fcdd2ea&chksm=8c411cf3bb3695e5ccd5fd6d396919fb815a8d56d0e9ed77b7e1e9fd3124d38f720b1755c2c6&cur_album_id=1989460124624551937&scene=189#wechat_redirect

线程池的优化:

  1. 线程本地队列,每个线程有一个本地队列,向线程池提交任务时,优先考虑本地线程队列,没有的提交到全局队列
  2. 多量拉任务,本地队列空的时候可以一次性多拿点任务,防止多次去取任务耗时,竞争会耗时
  3. 窃取任务,当当前任务队列为空且全局任务队列为空的时候,考虑偷其他线程的任务,但是注意轮询也会花时间,可以考虑设置轮训的最长距离
  4. 检察者,用于检测线程池的性能,比如隔一段时间统计线程是否运行,是否忙碌,然后取按规则扩容线程。
  5. 减少copy,能move就move

2. 构造函数可以用虚函数吗?

首先,构造函数是不能为虚函数的 调用构造函数后, 才能生成一个对象

3. 单例怎么实现的?如果不用once_call,自己怎么实现?

单例模式的作用:保证一个类仅有一个实例,并提供一个访问它的全局访问点。

私有化构造函数拷贝构造函数赋值运算符,防止多个实例被初始化

类内进行私有静态实例定义

几种实现:https://blog.csdn.net/unonoi/article/details/121138176

4. 工厂模式介绍一下?

没啥好讲的很简单

5. 常用的gcd的调试命令?

对应llldb
memory read
frame
bt
p
breakpoint
next
continue

6. 栈和堆的区别?

堆与栈实际上是操作系统对进程占用的内存空间的两种管理方式,主要有如下几种区别:
(1)管理方式不同。栈由操作系统自动分配释放,无需我们手动控制;堆的申请和释放工作由程序员控制,容易产生内存泄漏;

(2)空间大小不同。每个进程拥有的栈的大小要远远小于堆的大小。理论上,程序员可申请的堆大小为虚拟内存的大小,进程栈的大小 64bits 的 Windows 默认 1MB,64bits 的 Linux 默认 10MB;

(3)生长方向不同。堆的生长方向向上,内存地址由低到高;栈的生长方向向下,内存地址由高到低。

(4)分配方式不同。堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是由操作系统完成的,比如局部变量的分配。动态分配由alloca函数进行分配,但是栈的动态分配和堆是不同的,他的动态分配是由操作系统进行释放,无需我们手工实现。

(5)分配效率不同。栈由操作系统自动分配,会在硬件层级对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是由C/C++提供的库函数或运算符来完成申请与管理,实现机制较为复杂,频繁的内存申请容易产生内存碎片。显然,堆的效率比栈要低得多。

(6)存放内容不同。栈存放的内容,函数返回地址、相关参数、局部变量和寄存器内容等。当主函数调用另外一个函数的时候,要对当前函数执行断点进行保存,需要使用栈来实现,首先入栈的是主函数下一条语句的地址,即扩展指针寄存器的内容(EIP),然后是当前栈帧的底部地址,即扩展基址指针寄存器内容(EBP),再然后是被调函数的实参等,一般情况下是按照从右向左的顺序入栈,之后是被调函数的局部变量,注意静态变量是存放在数据段或者BSS段,是不入栈的。出栈的顺序正好相反,最终栈顶指向主函数下一条语句的地址,主程序又从该地址开始执行。堆,一般情况堆顶使用一个字节的空间来存放堆的大小,而堆中具体存放内容是由程序员来填充的。

7. 哪些情况下Vector迭代器会失效?

  1. ector在push_back的时候当容量不足时会触发扩容,导致整个vector重新申请内存.
  2. insert导致的迭代器失效有两种情况:
    (1)插入操作导致vector扩容,迭代器失效原因和push_back相同
    (2)插入操作引起vector内元素移动,导致被移动部分的迭代器失效
  3. erase导致迭代器失效
    删除操作引起vector内元素移动,导致被移动部分的迭代器失效。

你可能感兴趣的:(2023面试,c++,面试,笔记)