C++
1. const_cast
- 功能:用于去除变量的
const或volatile属性(非const对象的强制转换)。 - 注意:去除
const后修改数据时需小心,若对原本声明为const的数据进行修改,会导致未定义行为。
2. 三大特性
- 封装:
- 封装了数据,隐藏了实现细节,只暴露出必要的接口。
- 通过访问修饰符(
private、protected、public)控制数据的访问权限。
- 继承:
- 子类可以继承父类的资源、属性、函数等。
- 支持代码复用,子类可以添加新的属性或重写父类的方法。
- 多态:
- 子类可以重写(override)父类的虚函数,在运行时根据实际对象类型调用对应的方法。
- 通过基类指针或引用实现动态绑定。
3. 虚函数与纯虚函数
-
虚函数 (
virtual):- 通过
virtual关键字声明,可以被子类重写。 - 有正常的函数体,子类可以选择是否重写。
- 通过
-
纯虚函数 (
= 0):- 没有函数体,子类必须重写。
- 拥有纯虚函数的类称为抽象类,不能实例化。
4. static
- 静态存储:存储在静态区,生命周期贯穿程序整个运行周期。
- 应用场景:
- 静态成员变量:类共享的变量,每个对象实例共享一份内存。
- 静态函数:不依赖于具体对象,可以通过类名直接调用。
5. 上行转换与下行转换
-
上行转换(Upcasting):
- 子类指针或引用转换为父类指针或引用。
- 安全且无需强制转换。
-
下行转换(Downcasting):
- 父类指针或引用转换为子类指针或引用。
- 需要通过
dynamic_cast(确保安全)或static_cast。
6. weak_ptr
-
使用场景:
- 避免
shared_ptr之间的循环引用。
- 避免
-
特性:
- 不增加引用计数。
- 可以通过
lock()将weak_ptr提升为shared_ptr,如果资源已被释放,则返回空指针。
7. vector
-
查询:
- 访问元素时间复杂度为
O(1)(通过索引直接访问)。
- 访问元素时间复杂度为
-
插入:
- 末尾插入:若空间足够,时间复杂度为
O(1);否则触发扩容,为O(n)。 - 中间插入:需要将后续元素向后移动,时间复杂度为
O(n)。
- 末尾插入:若空间足够,时间复杂度为
8. 左值与右值
-
左值:
- 可以取地址的对象(如变量)。
-
右值:
- 不能取地址的临时对象(如返回值、字面量)。
- 通过
std::move()可以将右值的所有权转移给其他对象。
9. C++函数参数的内存分配
-
传值参数:
- 在栈上分配内存。
-
引用参数:
- 不复制数据,仅在栈上存储引用(指针)。
-
指针参数:
- 指针本身存储在栈上,指向的数据位置取决于具体分配(堆/栈)。
10. override
- 子类重写父类的虚函数时,显式标记为
override,可以帮助编译器检查是否真的重写了父类方法,避免错误。
11. 常见链表
- 单链表
- 双向链表
- 循环链表
- 跳表(用于高效查找,时间复杂度
O(log n))
12. 哈希冲突
哈希冲突:两个不同的键通过哈希函数得到相同的哈希值。
解决方法:
- 链式法:在同一哈希桶中存储冲突的元素。
- 线性探测:寻找下一个空闲位置存储元素。
- 二次探测:跳跃式寻找下一个空闲位置。
13. 死锁
-
四个必要条件:
- 请求保持:线程已持有资源,同时请求新的资源。
- 不可剥夺:资源不能被强行剥夺。
- 循环等待:多个线程形成资源等待的循环链。
- 互斥条件:资源只能被一个线程独占。
-
简述:
- 两个线程分别持有部分资源,互相请求对方的资源且不释放,导致僵持状态。
14. enum 与 enum class
-
enum:- 底层类型默认为
int,可以隐式转换为int。 - 同一作用域内,多个
enum的成员名可能冲突。
- 底层类型默认为
-
enum class:- 成员名必须通过
enum class名限定。 - 不支持隐式转换为
int,需要显式转换。
- 成员名必须通过
15. malloc 与 new 分配的内存位置
malloc和new:分配在堆区。
16. malloc/free 与 new/delete 的区别
-
malloc/free:- C语言函数。
- 返回
void *,需手动转换类型。 - 分配失败返回
NULL。 - 不会调用构造/析构函数。
-
new/delete:- C++操作符。
- 返回具体类型指针。
- 分配失败抛出异常(
std::bad_alloc),可以使用nothrow避免异常。 - 会自动调用构造/析构函数。
17. 手撕题
-
分组问题(并查集):
- 有些人不想和某人一组,判断是否可以分为两组。
- 使用并查集或二分图染色法解决。
-
青蛙跳台阶问题:
- 简单DP:
- 状态转移方程:
dp[i] = dp[i-1] + dp[i-2] - 初始化:
dp[0] = 1, dp[1] = 1
- 状态转移方程:
- 简单DP: