一. 各种容器的底层机制和常见面试题:
1.1 vector:
1.1.1 vector的底层原理:
vector的底层实现是三个指针:
struct _Vector_impl : public _Tp_alloc_type {
pointer _M_start;
pointer _M_finish;
pointer _M_end_of_storage;
};
start
和 finish
之间是已经被使用的空间范围(即 vector.size()
的大小),start
和 end_of_stroage
之间是vector底层数组的整个空间(即 vector.capacity()
的大小)。
所以 vector 这个类本身并不存储数据的内容,通过指针 start
指向真正的存储元素的数组的地址。
当现有的内存空间不够装下数据时(push_back(val)触发),vector会自动申请另一块更大的内存(1.5倍 或者 2倍),把原有的数据 拷贝 到新的内存空间,然后释放旧有内存空间。
当 clear清空 vector中的元素时(vector.clear()),其存储空间不释放,仅仅是情况内存上的数据。
例如:
vector<int> v;
for(int i = 0; i < 1000; i++) {
v.push_back(i);
}
cout << v.size() << " " << v.capacity() << endl;
v.clear();
cout << v.size() << " " << v.capacity() << endl;
------
1000 1024
0 1024
循环插入1000个元素到vector中,vector的size为1000,capacity为1024;
调用clear清空vector中的元素后,vector的size变为0,capacity仍为1024。
1.1.2 vector的reserve和resize的区别:
reserve 的作用是在vector初始化时,根据预估的所需要的内存大小 提前申请内存,目的是避免程序运行中重复的 申请、释放 内存空间,以提高程序的效率;
reserver修改的是vector的capacity的值,只表示一种尝试,当vector的现有实际size大于reserve(n)的n值时,vector不做任何修改。
resize 改变vector的实际大小,可能导致vector中的多余元素被删除,接受两个参数的resize不仅改变vector大小,也改变元素的默认值。
1.1.3 vector的size和capacity的区别:
size = finish - start;
表示的是vector中实际元素的 个数;capacity = end_of_storage - start;
表示的是vector当前分配的内存可以容纳的最多元素的 个数。
注意 size 和 capacity 表示的都是元素个数,不是vector内存的字节数。
1.1.4 vector的元素类型不能是引用:
vector的底层存储要求是连续的对象排列,引用不是对象,没有实际地址,因此vector的元素类型不能是引用。
1.1.5 释放vector的内存的方式:
clear、swap、shrink_to_fit。
- clear:v.clear(); //清空vector的元素,占用的内存不会释放,即size变0,capacity不变
- swap:vector<int> v2; //先定义个空的vector
- v2.swap(v);
swap 函数的效果是将 v1和v2 “整体