面试题答案
一键面试1. vector底层内存管理机制
vector
在C++中是一个动态数组。它在内存中维护一块连续的内存空间来存储元素。当元素数量超过当前分配的内存容量时,vector
会重新分配一块更大的内存空间,将原有的元素拷贝或移动到新的内存空间,然后释放旧的内存空间。
2. 自定义复杂类型对元素访问效率的影响
- 构造和析构开销:当
vector
进行内存重新分配时,对于自定义复杂类型,会涉及大量成员变量的构造和析构操作。例如,若自定义类型MyClass
包含多个成员变量如std::string
、自定义结构体等,每次重新分配内存时,这些成员变量都要重新构造和析构,这会消耗大量时间。 - 缓存不友好:由于复杂类型通常占用较大内存空间,可能导致
vector
中元素之间的内存间距变大,在CPU缓存中命中率降低。例如,假设CPU缓存一行数据为64字节,简单类型可能一行能存放多个元素,而复杂类型可能一个元素就超过64字节,这样在访问相邻元素时,可能频繁发生缓存未命中,降低访问效率。
3. 减少负面效应的设计方法
- 移动语义:在自定义类型中正确实现移动构造函数和移动赋值运算符。这样当
vector
重新分配内存时,能够以移动而非拷贝的方式转移对象,减少数据复制开销。例如:
class MyClass {
public:
MyClass(MyClass&& other) noexcept {
// 移动资源
}
MyClass& operator=(MyClass&& other) noexcept {
if (this != &other) {
// 释放当前资源
// 移动资源
}
return *this;
}
};
- 数据成员优化:尽量减少不必要的数据成员,只保留必要的成员变量。同时,对于复杂的成员变量,考虑使用指针或智能指针来延迟初始化或减少对象大小。例如,若有一个不常用的大对象成员,可以在需要时动态分配内存。
- 缓存友好设计:尽量保持对象大小合理,使
vector
中元素能够在缓存行中存放更多元素,提高缓存命中率。例如,可以将相关的小成员变量组合成结构体,减少内存碎片化。 - 避免不必要的虚函数:虚函数会增加对象的大小(因为需要存储虚函数表指针),尽量避免在自定义类型中使用不必要的虚函数,除非确实需要运行时多态性。