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 指向真正的存储元素的数组的地址。
2.vector的实现原理
vector是C++标准库中的一个容器类型,它是基于动态数组实现的。
vector内部使用了一个连续的内存块来存储元素。当创建一个vector对象时,会分配一块初始大小的内存空间,通常为默认大小(例如,32个元素的空间)。如果在向vector中添加元素时发现当前的内存空间不足以容纳更多元素,vector会动态地重新分配更大的内存,并将原有元素拷贝到新的内存空间中。
总之,vector采用动态数组的方式实现,通过动态内存分配和指针算术来管理元素的存储和访问,从而提供了高效的随机访问能力和动态扩展的功能。
3.vector的 内存增长机制:
当现有的内存空间不够装下数据时(push_back(val)触发),vector会自动申请另一块更大的内存(1.5倍 或者 2倍),把原有的数据 拷贝 到新的内存空间,然后释放旧有内存空间。
4.vector中size和capacity的区别
size是元素数量;capacity是容量;
循环插入1000个元素到vector中,vector的size为1000,capacity为1024;
调用clear清空vector中的元素后,vector的size变为0,capacity仍为1024。
5.为什么是1.5而不是2?
选择将容量增加1.5倍而不是2倍,主要是为了在性能和内存利用率之间做出一个平衡。
当容量增加2倍时,每次内存重新分配后,新的容量会是原来容量的2倍。这样的增长速度可以确保在大多数情况下足够的空间供应,减少内存重新分配的次数,提高性能。但是,如果只有一两个元素被添加到vector中,那么内存的浪费会相对较大
6.vector的reserve和resize的区别:
reserve 的作用是在vector初始化时,根据预估的所需要的内存大小 提前申请内存,目的是避免程序运行中重复的申请、释放内存空间,以提高程序的效率;
reserver修改的是vector的capacity的值,只表示一种尝试,当vector的现有实际size大于reserve(n)的n值时,vector不做任何修改。resize 改变vector的实际大小,可能导致vector中的多余元素被删除,接受两个参数的resize不仅改变vector大小,也改变元素的默认值。
7.vector和list有什么不同
- 存储方式:
- vector是一个动态数组,使用连续内存块存储元素。通过索引可以高效地访问元素,支持随机访问。
- list是一个双向链表,每个元素都包含一个指向前一个元素和后一个元素的指针。插入和删除操作可以在常量时间内完成,效率高,但随机访问效率较低。
- 内存占用和迭代器稳定性:
- vector使用连续的内存块存储元素,因此占用的内存比list更紧凑。同时,vector的迭代器在插入或删除元素后仍然有效(除非被删除的元素所在位置的迭代器)。
- list的每个元素都包含指针,因此占用的内存较大。同时,list的迭代器在插入或删除元素后仍然有效,不受影响。
基于上述特点,我们可以根据具体需求选择适合的容器类型。如果需要频繁地在中间或开头插入/删除元素,并且不关心随机访问性能,list可能是一个更好的选择。如果需要频繁进行随机访问,或者在尾部进行插入/删除操作,并且关心内存占用,vector可能更适合。
8.vector的随机访问的时间复杂度是多少?怎么优化他的查找速度
vector的随机访问时间复杂度是常数时间,即O(1)
要优化vector的查找速度,可以考虑以下几点:
- 使用二分查找:如果vector中的元素已经按照升序(或降序)排列,可以使用二分查找算法来快速找到目标元素。但要使用二分查找,必须先对vector进行排序。
- 使用无序容器:如果不需要保持元素的顺序,并且只关心查找速度,可以考虑使用无序容器,如unordered_map或unordered_set。这些容器使用哈希表实现,在平均情况下具有接近常数时间复杂度的查找操作。
9.vector的元素类型不能是引用:
vector的底层存储要求是连续的对象排列,引用不是对象,没有实际地址,因此vector的元素类型不能是引用。
10.释放vector的内存的方式:
- clear:清空vector的元素,占用的内存不会释放,即size变0,capacity不变
cpp
//原型:
v.shrink_to_fit(); //shrink_to_fit 将vector的capacity修改为与 size一致。作用是释放多余的内存空间
//注意 shrink_to_fit() 函数不接受参数
//使用shrink_to_fit 释放vector内存的写法:
v.clear();
v.shrink_to_fit(); //先调用clear将vector的size变为0,再使用shrink_to_fit将capacity也变为0
2.shrink_to_fit: