C++面试合计问题之vector

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有什么不同

  1. 存储方式:
    1. vector是一个动态数组,使用连续内存块存储元素。通过索引可以高效地访问元素,支持随机访问。
    2. list是一个双向链表,每个元素都包含一个指向前一个元素和后一个元素的指针。插入和删除操作可以在常量时间内完成,效率高,但随机访问效率较低。
  1. 内存占用和迭代器稳定性:
    1. vector使用连续的内存块存储元素,因此占用的内存比list更紧凑。同时,vector的迭代器在插入或删除元素后仍然有效(除非被删除的元素所在位置的迭代器)。
    2. list的每个元素都包含指针,因此占用的内存较大。同时,list的迭代器在插入或删除元素后仍然有效,不受影响。

基于上述特点,我们可以根据具体需求选择适合的容器类型。如果需要频繁地在中间或开头插入/删除元素,并且不关心随机访问性能,list可能是一个更好的选择。如果需要频繁进行随机访问,或者在尾部进行插入/删除操作,并且关心内存占用,vector可能更适合。

8.vector的随机访问的时间复杂度是多少?怎么优化他的查找速度

vector的随机访问时间复杂度是常数时间,即O(1)

要优化vector的查找速度,可以考虑以下几点:

  1. 使用二分查找:如果vector中的元素已经按照升序(或降序)排列,可以使用二分查找算法来快速找到目标元素。但要使用二分查找,必须先对vector进行排序。
  2. 使用无序容器:如果不需要保持元素的顺序,并且只关心查找速度,可以考虑使用无序容器,如unordered_map或unordered_set。这些容器使用哈希表实现,在平均情况下具有接近常数时间复杂度的查找操作。

9.vector的元素类型不能是引用:

vector的底层存储要求是连续的对象排列,引用不是对象,没有实际地址,因此vector的元素类型不能是引用。

10.释放vector的内存的方式:

  1. 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:

相关推荐
爬山算法几秒前
Maven(28)如何使用Maven进行依赖解析?
java·maven
神仙别闹19 分钟前
基于MFC实现的赛车游戏
c++·游戏·mfc
2401_8574396924 分钟前
SpringBoot框架在资产管理中的应用
java·spring boot·后端
怀旧66626 分钟前
spring boot 项目配置https服务
java·spring boot·后端·学习·个人开发·1024程序员节
小c君tt26 分钟前
MFC中 error C2440错误分析及解决方法
c++·mfc
李老头探索28 分钟前
Java面试之Java中实现多线程有几种方法
java·开发语言·面试
芒果披萨33 分钟前
Filter和Listener
java·filter
qq_49244844637 分钟前
Java实现App自动化(Appium Demo)
java
阿华的代码王国1 小时前
【SpringMVC】——Cookie和Session机制
java·后端·spring·cookie·session·会话
木向1 小时前
leetcode92:反转链表||
数据结构·c++·算法·leetcode·链表