vector与c语言中的数组类似,是数组的进阶,它能够根据需求改变自身的长度,就像数组一样,vector对其元素使用连续的存储位置,这意味着也可以使用指向其元素的常规指针上的偏移量来访问它们的元素,并且与在数组中一样高效,但与数组不同的是,它们的大小可以动态变化,其存储由容器自动处理。
vector的使用
构造函数
1.vector() 无参构造
2.vector(size_type n, const value_type& val = value_type()) 构造并初始化n个val
3.vector (const vector& x); 拷贝构造
4.vector (InputIterator first, InputIterator last); 使用迭代器进行初始化构造
iterator 的使用
1.begin + end(重点) 获取第一个数据位置的iterator/const_iterator, 获取最后一个数据的下一个位置的iterator/const_iterator
2.rbegin + rend 获取最后一个数据位置的reverse_iterator,获取第一个数据前一个位置的reverse_iterator
空间增长
1.size 获取数据个数
2.capacity 获取容量大小
3.empty 判断是否为空
4.resize(重点) 改变vector的size
5.reserve (重点) 改变vector的capacity
capacity的代码在vs和g++下分别运行会发现,vs下capacity是按1.5倍增长的,g++是按2倍增长的。这个问题经常会考察,不要固化的认为,vector增容都是2倍,具体增长多少是根据具体的需求定义的。
reserve只负责开辟空间,如果确定知道需要用多少空间,reserve可以缓解vector增容的代价缺陷问题。
resize在开空间的同时还会进行初始化,影响size。如果resize传参的数据小于size的时候,vector会删除数据,其他时候会插入数据,如果空间不够就扩容
增删查改
push_back 尾插
pop_back 尾删
find 查找。(注意这个是算法模块实现,不是vector的成员接口)
insert 在position之前插入val
erase 删除position位置的数据
swap 交换两个vector的数据空间
operator[] 像数组一样访问
迭代器失效
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对 指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器 底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即 如果继续使用已经失效的迭代器,程序可能会崩溃)。、
在vector中造成迭代器失效的几种原因
1. 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、 assign、push_back等。
v.resize(100, 8);
将有效元素个数增加到100个,多出的位置使用8填充,操作期间底层会扩容
v.reserve(100);
reserve的作用就是改变扩容大小但不改变有效元素个数,操作期间可能会引起底层容量改变
v.insert(v.begin(), 0);
v.push_back(8);
插入元素期间,可能会引起扩容,而导致原空间被释放
出错原因:以上操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃。
解决方式:在以上操作完成之后,如果想要继续通过迭代器操作vector中的元素,只需给 it重新赋值即可。
2. 指定位置元素的删除操作--erase
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了。
使用memcpy拷贝问题
假设模拟实现的vector中的reserve接口中,使用memcpy进行的拷贝,以下代码会发生什么问题?
问题分析:
1. memcpy是内存的二进制格式拷贝,将一段内存空间中内容原封不动的拷贝到另外一段内存空间中
2. 如果拷贝的是内置类型的元素,memcpy既高效又不会出错,但如果拷贝的是自定义类型元素,并且自定义类型元素中涉及到资源管理时,就会出错,因为memcpy的拷贝实际是浅拷贝。
结论:如果对象中涉及到资源管理时,千万不能使用memcpy进行对象之间的拷贝,因为 memcpy是浅拷贝,否则可能会引起内存泄漏甚至程序崩溃。
动态二维数组理解
vector<vector<int>> vv(n); 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类型的,每行没有包含任何元素,如果n为5时如下所示: