C++面试总结
前言
最近又去接受大环境的毒打了,基础知识篇已经完全无法支撑目前的面试要求了,现在把一些面试点总结下来,一方面方便自己学习总结进步,另一方面供各位准离职的朋友参考。
问到的知识点
首先
void attribute((constructor)) init()
{
//准备一个最最最熟悉的项目!犄角旮旯都熟悉的!!!;
}
1、目前用到的C++多少?
C++11
2、C++11的新特性了解吗?
STL、智能指针、右值引用、STL容器、lambda表达式
2.1 STL
什么是STL?由几部分组成?
STL的设计思想是基于泛型编程和模板元编程,它提供了高度可复用、高效的数据结构和算法
容器、算法、迭代器、仿函数
STL包含了哪些容器?
1>. 序列容器(Sequence Containers):
std::vector
: 动态数组,支持快速随机访问和动态大小调整。std::deque
: 双端队列,支持快速随机访问和两端的插入和删除操作。std::list
: 双向链表,支持快速插入和删除操作。
2>. 关联容器(Associative Containers):
std::set
: 有序集合,不允许重复元素。std::multiset
: 有序多重集合,允许重复元素。std::map
: 有序映射,以键-值对的形式存储元素,不允许重复的键。std::multimap
: 有序多重映射,允许重复的键。
3>. 无序容器(Unordered Containers):
std::unordered_set
: 无序集合,基于哈希表实现。std::unordered_multiset
: 无序多重集合,允许重复元素,基于哈希表实现。std::unordered_map
: 无序映射,以键-值对的形式存储元素,基于哈希表实现。std::unordered_multimap
: 无序多重映射,允许重复的键,基于哈希表实现。
4>. 容器适配器(Container Adapters):
std::stack
: 栈,基于其他序列容器实现。std::queue
: 队列,基于其他序列容器实现。std::priority_queue
: 优先队列,基于其他序列容器实现。
这些容器的底层分别是什么实现的?
–>1. 序列容器:
std::vector
: 底层通常是一个动态数组,支持随机访问。元素在内存中连续存储,可以通过索引进行快速访问。std::deque
: 底层通常是一个由多个定长数组构成的序列,支持两端插入和删除。std::list
: 底层是一个双向链表,支持在任意位置进行快速插入和删除。
–>2. 关联容器:
std::set
和std::multiset
: 通常使用平衡二叉搜索树(如红黑树)作为底层实现,保证元素的有序性和快速查找。std::map
和std::multimap
: 通常使用平衡二叉搜索树作为底层实现,以键值对的形式存储数据,保证快速的查找和插入操作。
–>3. 无序容器:
std::unordered_set
和std::unordered_multiset
: 底层通常是一个哈希表,用于实现快速的查找和插入操作。std::unordered_map
和std::unordered_multimap
: 也是使用哈希表作为底层实现,以键值对的形式存储数据。
–>4. 容器适配器:
std::stack
、std::queue
和std::priority_queue
:这些容器适配器通常基于序列容器进行实现,例如std::deque
或std::vector
。
这些底层数据结构的选择是基于不同的需求和性能考虑`std::vector`适合需要快速随机访问的情况,而`std::list`适合频繁的插入和删除操作。对于关联容器,底层的平衡二叉搜索树可以保证较快的查找操作,而哈希表则可以实现常数时间复杂度的查找和插入操作。
注意:这些东西在背会的前提下需要结合自己的项目了解在哪里使用,为什么这么使用!!!
2.2 智能指针
auto_ptr—转移所有权(现已废弃)
share_ptr–共享同一个对象,注意回环
weak_ptr—为了解决share_ptr回环无法正常释放问题而引出的
unique_ptr 不可复制和赋值
2.3右值引用
转移所有权
2.4 lambda表达式
3、怎么理解设计模式?(设计模式是什么?分哪几类?常用的是哪几种)
注意:这里千万不要自己给自己挖坑,一定要讲自己熟悉的设计模式!结合项目!!!
设计模式的概念+类型(创建型、结构型、行为性)+设计模式的六大原则(开闭原则、单一职责原则、依赖倒置原则、迪米特法则、里氏替换原则、接口隔离原则)
创建型(5种):描述类的创建 比如单例模式、工厂模式
结构型(7种):描述类与对象的关系 比如
行为型(11种):描述对象与对象的行为和关系 比如观察者模式
能具体讲一下观察者/工厂模式吗?以及你在项目的哪里使用到观察者/工厂模式?
…根据具体项目说明…
4、进程间的通信方式有哪些?
这里一定要区分清楚进程和线程,会问
常见的进程通信方式有7种:管道、命名管道、消息队列、共享内存、信号量semaphore、套接字Socket、信号signal
管道:只能用于具有亲缘关系的进程之间的通信(也是父子进程或者兄弟进程之间)比如fork()
管道分为无名管道和命名管道
无名管道:父进程创建管道,并在管道中写入数据,子进程从管道中读出数据
命名管道:
消息队列:就是一个消息的链表,是一系列保存在内核中的消息列表,用户进程可以向消息队列中添加和读取消息
消息队列与管道通信相比的优势:根据自定义条件接收特定类型的消息
共享内存win&linux
共享内存允许两个或多个进程共享一个给定的存储区。采用共享内存的一个主要好处是效率高
linux下共享内存的常用函数:mmap(建立共享内存映射) munmap(解除共享内存映射)
shmget(获取共享内存区域的ID) shmat(建立映射共享内存) shmdt(解除共享内存映射)
信号量:信号量用于进程间同步,若要在进程间传递数据需要结合共享内存
linux下信号量相关函数 sem_init sem_wait sem_post sem_destory
5、知道死锁吗?如何避免死锁?
死锁的四个条件:互斥、不可剥夺、请求和保持、回环
避免死锁:破坏“循环”条件—设置优先级
破坏“不可剥夺”条件:当一个进程的需求资源无法被满足的时候,释放已经持有的资源
破坏“请求和保持”条件:进程运行初期就要申请进程运行的全部资源
6、GDB调试会使用吗?如果项目出现了core文件如何调试?描述一下调试过程
GDB调试命令见上篇
GDB调试命令
7、模板成员的模板函数为什么不能用virtual修饰?
模板是在编译期间生成和实例化的,虚函数是运行期才确认下来的,这就产生矛盾了
模板类头文件和源文件是否能够分开?
最好不分开,都写在头文件中,如果头文件和源文件分开,需要在源文件中实例化所有需要使用的对象来通过编译。
这是由于
:对C++编译器而言,当调用函数的时候,编译器只需要看到函数的声明。当定义类类型的对象时,编译器只需要知道类的定义,而不需要知道类的实现代码。因此,因该将类的定义和函数声明放在头文件中,而普通函数和类成员函数的定义放在源文件中。
但在处理模板函数和类模板时,问题发生了变化。要进行实例化模板函数和类模板,要求编译器在实例化模板时必须在上下文中可以查看到其定义实体;而反过来,在看到实例化模板之前,编译器对模板的定义体是不处理的——原因很简单,编译器怎么会预先知道 typename 实参是什么呢?因此模板的实例化与定义体必须放到同一翻译单元中
8、有使用到select和epoll吗?两者有何区别?
(未完待续)