STL容器:vector
一、vector与string
相同:
string和vector都是STL中的顺序容器,他们的底层均使用动态数组实现,支持随机访问、动态扩容、并提供相似的成员函数。(所以他们提供的常见接口基本相似)
不同:
用途:string专门用来存储字符(char/wchar_t),提供字符串特有的操作(c_str()、substr()、字符串拼接+等),而vector是通用容器,可以存储任意的类型。
接口差异:string支持字符串字面量直接赋值、比较,而vector更侧重泛型数据操作(如迭代器、算法库适配)
总结:string是特化于字符的vector,但增加了字符串的专属功能。
二、vector中迭代器的失效
迭代器底层实际上就是一个指针(或者对指针的封装),其充当了容器和算法之间的粘合剂,它提供了遍历和访问容器中元素的统一接口,使得STL算法能够独立于底层容器的具体数据结构,从而实现高度的通用性和效率,总的来说迭代器就是能用类似指针的语法,安全高效统一地遍历所有STL容器的工具
注意:迭代器的失效只是运行时的错误,编译器不会警告
①改变底层空间的操作(insert/resize/reserve/assign)
会引起其底层空间改变的操作都有可使迭代器失效
当insert产生扩容时,reserve开辟新空间,但pos指针仍指向原空间位置,pos变成野指针导致迭代器失效,事实上:即使我们将代码完善,只要在insert之后,我们默认迭代器(insert之后的迭代器)都失效了,在没有更新失效的迭代器之前,我们不能再正常使用
②erase后编译器会标记迭代器(就会失效)
erase会直接覆盖要删除掉的元素,在直接++it的情况下,会存在漏判的情况,且有可能导致it直接跳过end,造成越界访问
erase删除pos位置元素后,删除位置之后的元素都需要向前移动,没有导致底层空间的变化,理论上迭代器不会失效,但vs默认迭代器失效
解决迭代器失效的办法:在使用前对迭代器重新赋值
三、vector的拷贝构造
浅拷贝:只复制指针的值(内存地址),而不复制指针所指向的数据,结果是两个指针指向同一块内存,修改其中一个另一个也会受到影响,易导致双重释放
深拷贝:不仅复制指针,还会为新指针分配新的内存空间,并将原指针指向的数据完整地复制一份,结果是两个对象拥有各自独立的数据,互不干扰
1.vector的拷贝构造
vector的拷贝构造都是深拷贝,赋值操作也会调用拷贝构造同样是深拷贝
2.使用memcpy拷贝的问题
memcpy是内存中的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另一段内存空间中,如果拷贝的是自定义类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及达到资源管理时,就会出错,因为memcpy的拷贝构造实际是浅拷贝
四、vector的常用接口
1.vector的定义(构造)
①无参默认构造
②拷贝构造
③构造并初始化n个val
2.vector iterator的使用(迭代器)
①获取第一个数据位置和最后一个数据下一个位置的iterator/const_iterator
②获取最后一个数据位置和第一个数据前一个位置的reverse_iterator
3.vector空间增长
①size:获取数据个数
②capacity:获取容量大小
③empty:判断是否为空
④resize:改变vector的size
resize在开空间的同时还会进行初始化,影响size
⑤reserve:改变vector的capacity
4.vector的增删查改
①push_back:尾插
②pop_back:尾删
③find:查找(算法模块实现,非vector的成员接口)
④insert:在pos之前插入val
⑤erase:删除pos位置的数据
⑥swap:交换两个vector的数据空间
⑦operator[]:像数组一样访问