一、问题总览
- cpp重载和重写的区别
- cpp虚函数表
- 指针和引用的区别
- linux的常用开发指令
- linux编译运行程序的指令
- 关键字inline
- 什么场景使用内联
- 如何避免内存泄露
- map和unordered_map
- 引用外部头文件双引号和尖括号的区别
- private、public、protected的区别
- new和malloc的区别
二、技术面
2.1 cpp重载和重写的区别
答:
- 重载:函数名必须相同,但参数列表必须不同(参数类型、个数、顺序不同),与返回值类型无关。
- 重写:子类函数必须与父类的虚函数函数名、参数列表、返回值类型完全相同(协变返回类型除外),且父类函数必须声明为virtual。
2.2 cpp虚函数表
答:
虚函数表(Virtual Table,简称 Vtable)是 C++ 实现多态(Polymorphism)的底层机制,用于在运行时确定应该调用哪个虚函数版本。它是编译器在编译阶段为包含虚函数的类生成的一张函数指针表,存储该类所有虚函数的地址。
2.1.1 单一继承场景
假设有父类Animal和子类Dog,其中Animal包含虚函数makeSound(),Dog重写该函数:
class Animal
{
public:virtual void makeSound() { cout << "动物叫" << endl; }virtual void eat() { cout << "动物吃" << endl; }
};class Dog : public Animal
{
public:void makeSound() override { cout << "汪汪叫" << endl; }// 未重写eat(),继承父类版本
};
编译器会生成两个虚函数表:
Animal 的虚函数表:[&Animal::makeSound, &Animal::eat]
Dog 的虚函数表:[&Dog::makeSound, &Animal::eat](重写的makeSound替换父类版本,eat继承父类)
Animal对象:
+----------+
| Vptr | --> 指向Animal的虚函数表
+----------+Dog对象:
+----------+
| Vptr | --> 指向Dog的虚函数表(继承自Animal的部分)
+----------+
2.3 指针和引用的区别
2.4.1 关键区别对比
- 指针
- 本身是一个变量,占用内存空间(32 位系统 4 字节,64 位系统 8 字节),存储的是目标变量的地址。
- 可以被重新赋值,指向其他同类型变量。
int a = 10;
int* p; // 未初始化(野指针,禁止直接使用)
p = &a; // 后续可指向a
p = nullptr; // 可指向空
- 内存
- 声明时必须初始化,且一旦绑定某个变量,终身不能再绑定其他变量(从一而终)。
- 只是目标变量的别名,不占用额外内存空间(编译器处理为常量指针,但语法上隐藏了指针特性)。
- 一旦绑定变量,不能改变绑定对象(但可以修改目标变量的值)。
int a = 10, b = 20;
int& r = a; // 正确:初始化绑定a
// int& r; // 错误:引用必须初始化
r = b; // 不是重新绑定,而是将b的值赋给a(r仍绑定a)
2.4 linux的常用开发指令
xxx
2.5 linux编译运行程序的指令
xxx
2.6 关键字inline
inline 是 C++ 中的一个关键字,用于建议编译器将函数调用替换为函数体本身(即 “内联展开”),以减少函数调用的开销(如栈帧创建、参数传递等),从而提高程序运行效率。
- 核心作用:减少函数调用开销
- 函数调用时,系统需要执行以下操作(有性能成本):
- 保存当前函数的栈帧状态(返回地址、局部变量等)。
- 传递参数,跳转到被调用函数的入口。
- 函数执行完毕后,恢复栈帧并返回。
内联函数通过 “原地展开” 避免这些操作,适合短小简单的函数
2.7 什么场景使用内联
短小、频繁调用、性能敏感的函数才考虑内联,避免盲目使用导致代码膨胀。
2.8 如何避免内存泄露
- 优先使用智能指针(C++11 及以上)
- 避免手动管理动态内存
- 严格遵循 “谁申请,谁释放” 原则
- 避免在异常场景下泄漏