秋招日寄|嵌入式模拟面试拷打|20241031
发现上次更新还是九月份,想一想也确实这一个月很少遇到八股盛宴的面试了,今天回顾一下,发现很多题目都已经不再熟悉,果然,死记硬背的八股,终究不是自己的。
1. C++ 程序编译过程
C++ 程序的编译过程分为四个主要步骤:
- 预处理:处理
#include
、#define
等指令,生成预处理后的代码。此步骤会进行宏替换、条件编译等。 - 编译:将预处理后的代码翻译为汇编语言。这一阶段进行语法分析、语义分析等。
- 汇编:将汇编代码转换为机器码,生成目标文件(
.obj
或.o
文件)。 - 链接:将多个目标文件及其依赖的库文件链接为最终的可执行文件,解决符号引用并合并代码段。
2. C++ 内存管理
C++ 提供两种内存管理方式:
- 静态内存分配:在编译时分配,大小和生命周期固定,适用于全局变量和局部静态变量。
- 动态内存分配:通过
new
和delete
操作符在堆上动态分配和释放内存。动态内存允许在运行时决定内存大小,但需要手动管理,避免内存泄漏。
3. 栈和堆的区别
- 栈:自动管理,函数调用时自动分配和释放,速度快但大小有限,适合局部变量和函数调用。
- 堆:手动管理,适用于动态内存分配。灵活但较慢,容易导致内存泄漏或碎片化。
4. 变量的区别
- 局部变量:在函数或代码块中定义,生命周期在函数结束时终止。
- 全局变量:在所有函数外部定义,生命周期随程序运行期存在,作用域为整个文件。
- 静态变量:局部静态变量在函数内部定义,但生命周期贯穿整个程序。全局静态变量仅在定义文件可见。
- 动态变量:通过
new
分配,生命周期由程序员管理,需手动释放。
5. 全局变量定义在头文件中的问题
将全局变量定义在头文件中会导致在多个源文件中重复定义同一变量,产生链接错误。应将全局变量的定义放在一个源文件中,并在头文件中使用 extern
声明。
6. 单继承与多继承的虚函数表结构
- 单继承:每个类都有一个虚函数表(vtable),包含该类及其父类的虚函数指针。对象中有一个指向该表的虚表指针(vptr)。
- 多继承:每个基类部分都有自己的虚函数表,派生类对象中包含多个虚表指针,分别指向不同基类的虚函数表。
7. 内存对齐
内存对齐是指数据在内存中的地址需满足特定倍数的要求,以提高内存访问效率。未对齐的数据访问可能导致性能下降和多次内存访问。
8. 什么是内存泄漏
内存泄漏指分配的内存未被释放,导致无法再次使用。这通常发生在忘记释放动态分配的内存,可能导致系统内存耗尽。
9. 如何防止内存泄漏?内存泄漏检测工具的原理
- 防止内存泄漏的方法:
- 使用智能指针,如
std::unique_ptr
和std::shared_ptr
,自动管理内存。 - 确保所有
new
的对象都有相应的delete
。 - 在析构函数中释放动态分配的资源。
- 使用智能指针,如
- 内存泄漏检测工具:
- Valgrind:监控内存分配和释放,检测泄漏。
- AddressSanitizer:编译时插入额外检查代码,运行时检测非法内存访问和泄漏。
10. 智能指针的种类及实现原理
unique_ptr
:独占所有权,不能复制,使用std::move
转移所有权。shared_ptr
:共享所有权,使用引用计数管理,引用计数为零时释放资源。weak_ptr
:不控制资源,避免shared_ptr
的循环引用。
11. 智能指针应用举例
std::unique_ptr<int> p1(new int(10));
std::shared_ptr<int> p2 = std::make_shared<int>(20);
void func() {
std::shared_ptr<int> p3 = p2; // p2, p3 共享同一内存
}
12. 如何将 unique_ptr
赋值给另一个 unique_ptr
对象
unique_ptr
不能复制,可以通过移动语义转移所有权:
std::unique_ptr<int> p1(new int(10));
std::unique_ptr<int> p2 = std::move(p1); // p1 失去所有权,p2 获得所有权
13. 使用智能指针可能出现的问题及解决方法
- 循环引用:
shared_ptr
可能导致循环引用,造成内存泄漏。解决方法是使用weak_ptr
打破循环引用。
struct A;
struct B;
struct A {
std::shared_ptr<B> b_ptr;
};
struct B {
std::weak_ptr<A> a_ptr;
};
14. 在 Visual Studio 中检测内存泄漏的方法
Visual Studio 提供内存泄漏检测功能,可以在代码中插入 _CrtDumpMemoryLeaks()
函数:
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
int main() {
_CrtDumpMemoryLeaks(); // 在程序结束时自动检测泄漏
return 0;
}
15. 深拷贝与浅拷贝
- 浅拷贝:只复制指针,多个对象共享同一资源。
- 深拷贝:复制指向的资源,创建独立对象,防止共享资源。
class MyClass {
int* data;
public:
MyClass(int val) : data(new int(val)) {}
MyClass(const MyClass& other) : data(new int(*other.data)) {} // 深拷贝
~MyClass() { delete data; }
};
#牛客创作赏金赛#秋招日寄|嵌入式模拟面试拷打 文章被收录于专栏
一些八股模拟拷打Point,万一有点用呢