面试题答案
一键面试vector和deque在内存分配和释放机制上的主要区别
- 内存分配方式
- vector:vector通常分配一块连续的内存空间来存储元素。这意味着它的元素在内存中是紧密排列的,如同数组一样。当vector的容量(capacity)不足以容纳新元素时,它会重新分配一块更大的连续内存空间,将原有的元素复制到新空间,然后释放旧空间。这种重新分配内存的操作代价较高,因为涉及到大量数据的复制。
- deque:deque(双端队列)并不保证所有元素在内存中是连续存储的。它通常由多个固定大小的内存块组成,这些内存块通过一个内部的索引结构(通常是一个数组)进行管理。这种结构使得deque在两端插入和删除元素时效率较高,因为不需要像vector那样频繁地重新分配内存。
- 内存释放时机
- vector:当vector对象被销毁时,它会自动释放其占用的所有内存。然而,当从vector中删除元素时,除非删除的是所有元素(即调用
clear()
或erase()
删除所有元素),否则vector并不会立即释放内存。这是因为vector为了避免频繁的内存重新分配,会保留一定的容量(capacity),使得后续插入操作可以更高效地进行。 - deque:当deque对象被销毁时,它会释放所有相关的内存块。与vector不同,deque在删除元素后,可能会根据内部的算法和状态,适时地释放不再使用的内存块,从而更及时地回收内存。
- vector:当vector对象被销毁时,它会自动释放其占用的所有内存。然而,当从vector中删除元素时,除非删除的是所有元素(即调用
在删除部分元素后及时回收vector内存的思路及代码示例
- 思路
- 可以利用
std::vector
的shrink_to_fit()
成员函数。这个函数会尝试将vector
的容量(capacity)减小到与当前大小(size)相同,从而释放多余的内存。在删除部分元素后调用shrink_to_fit()
,可以达到及时回收内存的目的。需要注意的是,shrink_to_fit()
是一个请求性操作,标准库并不保证一定会减小容量,实际效果可能因实现而异。
- 可以利用
- 代码示例
#include <iostream>
#include <vector>
#include <string>
class MyClass {
public:
MyClass() { std::cout << "MyClass constructed" << std::endl; }
~MyClass() { std::cout << "MyClass destructed" << std::endl; }
};
int main() {
std::vector<MyClass> myVector;
// 向vector中添加大量元素
for (size_t i = 0; i < 10000; ++i) {
myVector.emplace_back();
}
std::cout << "Initial size: " << myVector.size() << ", capacity: " << myVector.capacity() << std::endl;
// 删除部分元素
myVector.erase(myVector.begin() + 2000, myVector.begin() + 8000);
std::cout << "Size after erase: " << myVector.size() << ", capacity: " << myVector.capacity() << std::endl;
// 尝试回收内存
myVector.shrink_to_fit();
std::cout << "Size after shrink_to_fit: " << myVector.size() << ", capacity: " << myVector.capacity() << std::endl;
return 0;
}
在上述代码中,首先创建了一个MyClass
类型的vector
并添加了大量元素。然后删除了部分元素,接着调用shrink_to_fit()
尝试回收内存。通过输出size
和capacity
,可以观察到内存回收的效果。