|
发表于 昨天 14:15
|
查看: 18 |
回复: 0
腾讯wxg一面面经
虚函数、虚表、虚指针解释一下,分别在哪个时间段创建的。
虚函数:类中通过virtual关键字声明的函数,允许在派生类中被重写,实现多态。
虚表(虚函数表):一个存储类的虚函数地址的表,在编译时期创建,每个含有虚函数的类都有一个虚表。
虚指针(vptr):一个指针,指向对象的虚表,在对象实例化时(运行时)被创建,并初始化指向类的虚表。
select、poll、epoll的区别解释一下- select: 它的文件描述符集合大小有限(通常受FD_SETSIZE宏限制),每次调用都需要复制整个文件描述符集,且在返回后需要遍历整个集合来找出活跃的文件描述符,这让它在处理大量文件描述符时效率较低。
- poll: 类似于select,但它不受文件描述符数量的限制,因为它使用动态数组(而不是固定大小的位数组)。同样,在每次调用时需要复制整个数组,并在返回后遍历数组以找出活跃的文件描述符。
- epoll: 仅在Linux系统上可用,它使用了一个事件列表,所以不需要像select或poll那样复制和遍历整个文件描述符集。epoll在首次监视某个文件描述符时向内核注册文件描述符,之后不需要再次注册,且当文件描述符就绪时,它只返回那些状态发生变化的文件描述符,这大大提高了效率,尤其适合处理大量文件描述符的场景。
内存池的基本原理解释一下。
内存池的基本原理是预先在内存中分配一大块连续的空间,并将这块空间划分为大小相等或不等的小块,用于满足程序运行时的内存分配请求。当程序请求分配内存时,内存池会从这些预分配的小块中找到一个合适的块返回,而不是直接向操作系统请求。同样,当内存被释放时,它会返回到内存池中,而不是归还给操作系统。这种方式可以减少频繁向操作系统申请和释放内存所造成的开销和碎片化问题,从而提高内存分配和回收的效率。
左值引用和右值引用的区别解释一下,为什么需要右值?
左值引用:是对可寻址(即可以取地址)且非临时的对象的引用,例如变量。左值引用用&表示。
右值引用:是对临时对象(即将被销毁、不能取地址的对象)或可移动对象的引用,它扩展了对象的生命周期。右值引用用&&表示。
为什么需要右值:右值引用主要用于实现移动语义和完美转发。
- 移动语义允许资源(如动态内存)从一个对象转移到另一个对象,减少不必要的临时对象复制,优化性能。
- 完美转发允许模板函数将其接收到的参数以原来的值类别(左值或右值)转发到其他函数,这在模板编程和函数重载解析中很有用。
智能指针的基本原理,引用计数是线程安全的吗?智能指针是线程安全的吗?
智能指针的基本原理是通过封装一个原始指针,在对象的生命周期管理上提供自动化处理
引用计数在std::shared_ptr中默认是线程安全的,即多个线程同时创建或销毁同一shared_ptr实例是安全的,因为修改引用计数的操作是原子的。
智能指针的线程安全性取决于其操作。对于智能指针本身的管理(如赋值和析构),std::shared_ptr是线程安全的。但是,多个线程访问智能指针管理的对象并不一定是线程安全的,需要额外的同步机制来保护被管理对象。
多线程访问单例,你要怎么办?
双重检查锁定模式(Double-Check Locking)。步骤如下:
- 在访问单例对象之前,首先检查对象是否已经被创建,以避免锁定开销。
- 若单例对象未被创建,则进入同步块。同步块内部再次检查对象是否已创建,以防止多个线程同时通过第一次检查。
- 如果确认单例对象未被创建,此时创建单例实例。
stl::vector数据存在哪里?为什么不能在栈上?
std::vector的数据实际存储在堆(Heap)上。这是因为std::vector需要能够动态地增长或缩小其大小,而堆内存提供了动态内存分配的能力。栈(Stack)上的空间是有限且固定大小的,适合存储大小在编译时期就已确定的局部变量,不适合存储大小可变的std::vector。
为什么栈比堆快?
栈比堆更快主要是因为其内存分配方式和访问速度。栈内存由操作系统自动管理,分配和释放速度非常快,因为它使用连续的内存块,并以后进先出的顺序进行访问。相反,堆内存分配更为灵活但也更复杂,需要程序员手动分配和释放,且可能产生内存碎片,这会影响访问速度。此外,栈内存访问通常涉及更少的指令和间接性。
unordered_map底层是什么?
unordered_map底层实现是一个哈希表。它通过使用哈希函数来把键转换为哈希值,然后根据这个哈希值把元素存储在相应的桶中。在碰到哈希冲突时,会通过链接法解决,即在同一桶中用链表链接存储所有哈希值相同的元素。
C++入口函数是什么?main函数之前执行的是什么函数?
C++的入口函数是main函数。在main函数执行之前,C++运行时会执行一些环境准备的工作,包括初始化静态存储持续期内的对象、执行非局部对象的构造函数等。这些通常涉及到全局对象的构建、静态对象的初始化,以及C++标准库和运行时库的初始化。不同的编译器和平台可能会有不同的启动例程,比如GCC的_start函数,在调用main函数之前设置程序运行的环境。
LeetCode 907
给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例 1:
输入:arr = [3,1,2,4]
输出:17
解释:子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。
示例 2:
输入:arr = [11,81,94,43,3]输出:444
提示:
- 1 <= arr.length <= 3 * 104
- 1 <= arr <= 3 * 104
解题步骤如下:
- 单调栈:使用单调递增栈存储数组元素的索引,帮助快速找到每个元素左右两边第一个比它小的元素位置。
- 遍历数组:对数组每个元素进行遍历,对于每个遍历到的元素,进行以下操作:
- 当栈不为空且当前元素小于栈顶元素对应的数组值时,弹出栈顶元素,并计算以该栈顶元素对应的值为最小值的子数组对总和的贡献。
- 将当前元素的索引入栈。
- 处理栈中剩余元素:遍历结束后,栈中可能还有元素。这些元素对应的值是它们右侧所有子数组的最小值。类似地,计算它们对总和的贡献。
- 计算结果:遍历过程中累加每次计算的子数组最小值的总和。
- 返回结果:因为结果可能非常大,根据题目要求,返回总和对 10^9 + 7 取模的结果。
顺便吆喝一句,民族企业大厂,前后端测试捞人,感兴趣的来!
|
温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【 投诉建议】板块发帖举报。
|