1.概述
2.成员函数
2.1构造函数
vector() | 无参构造 |
vector(size_type n, const value_type& val = value_type()) | 构造并初始化n个val |
vector (const vector& x) | 拷贝构造 |
vector (InputIterator first, InputIterator last) | 使用迭代器进行初始化构造 |
2.2iterator 的使用
(end和rend返回的迭代器是指向最后一个元素后面的位置)
begin + end | 获取第一个数据位置的 iterator/const_iterator , 获取最后一个数据的下一个位置的iterator/const_iterator |
rbegin + rend | 获取最后一个数据位置的 reverse_iterator ,获取第一个数据前一个位置的reverse_iterator |
2.3空间增长
size | 获取数据个数 |
capacity | 获取容量大小 |
empty | 判断是否为空 |
resize | 改变 vector 的 size |
reserve | 改变 vector 的 capacity |
resize 和 reserve的对比:
reserve是容器预留空间,但在空间内不真正创建元素对象,没有添加新的对象之前,不能访问容器内的元素,reserve()函数和容器的capacity息息相关:
如果n>容器的当前capacity,该函数会使得容器重新分配内存使capacity达到n
如果n<=capacity,该函数调用不会导致内存重新分配,并且容器的capacity不会改变
reserve()避免多次不必要的扩容,不会影响size,不会改变任何元素
vs下capacity是按1.5倍增长的,g++是按2倍增长的
resize是改变容器的size大小,且创建对象,可以访问容器内的对象
如果n<当前容器的size,则将元素减少到前n个,移除多余的元素(并销毁)
如果n>当前容器的size,则在容器中追加元素,如果val指定了,则追加的元素为val的拷贝,否则,默认初始化
如果n>当前容器capacity容量,内存会自动重新分配
2.4增删查改
push_back | 尾插 |
pop_back | 尾删 |
find | 查找,注意这个是算法模块实现,不是vector的成员接口 |
insert | 在position之前插入val |
erase | 删除position位置的数据 |
swap | 交换两个vector的数据空间 |
operator[] | 像数组一样访问 |
容器类 | 插入 | 删除 |
list | 所有迭代器不失效 | 有且仅有被删除的节点的迭代器才失效 |
vector | 当 vector 的容量(capacity)不改变时, 只失效之后的迭代器, 否则全部失效 | 被删除节点之后的迭代器全部失效 |
set,map | 所有迭代器不失效 | 有且仅有被删除的节点的迭代器才失效 |
insert导致的失效:
会引起其底层空间改变的操作都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等操作,都有可能会导致vector扩容,也就是说vector底层原理旧空间被释放掉,而在打印时,it还使用的是释放之间的旧空间,在对it迭代器操作时,实际操作的是一块已经被释放的空间,而引起代码运行时崩溃
iterator insert(iterator pos, const T& x) {assert(pos >= _start);assert(pos <= _finish);if(_finish == _endOfStorage) {size_t len = pos - _start;reserve(capacity() == 0 ? 4 : capacity() * 2);//发生扩容,pos的位置不再正确,需要更新pos = _start + len;}iterator it = _finish - 1;while (it >= pos) {*(it + 1) = *it;it--;}*pos = x;_finish++;return _start;}void test_vector7() {//迭代器失效1:inset插入vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(5);v1.push_back(6);v1.push_back(7);v1.push_back(8);print_vector(v1);//insert以后,发生了扩容,it失效了,因为it指向旧空间 解决:更新it//尽管我们在insert函数里更新了pos,但是pos是it的形参拷贝,pos改变不影响it,//就算传参为&,但是begin()就传不了,因为begin是传值返回,返回临时变量具有常性,//就得加const,就矛盾了//如果想要继续通过迭代器操作vector中的元素,只需给it重新赋值即可vector<int>::iterator it = v1.begin() + 3;cout << *it << endl;v1.insert(it, 40);print_vector(v1);cout << *it << endl;}//测试7 > ://1 2 3 4 5 6 7 8//4//1 2 3 40 4 5 6 7 8//- 572662307
erase导致的失效:
erase删除pos位置元素后,pos位置之后的元素会往前搬移,没有导致底层空间的改变,理论上讲迭代器不应该会失效,但是:如果pos刚好是最后一个元素,删完之后pos刚好是end的位置,而end位置是没有元素的,那么pos就失效了。因此删除vector中任意位置上元素时,vs就认为该位置迭代器失效了
iterator erase(iterator pos) {assert(pos >= _start);assert(pos < _finish);iterator it = pos+1;while (it < _finish) {*(it - 1) = *it;it++;}_finish--;return pos;}void test_vector8() {//迭代器失效2:删除偶数vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(4);v1.push_back(5);print_vector(v1);vector<int>::iterator it = v1.begin();while (it!=v1.end()){if (*it % 2 == 0) {v1.erase(it);}++it;解决:返回指向删除元素位置下一个的迭代器//if (*it % 2 == 0) {// it = v1.erase(it);//}//else {// ++it;//}}print_vector(v1);}//测试8 > ://1 2 3 4 4 5//1 3 4 5
2.5使用memcpy拷贝问题
void reserve(size_t n) {int len = size();if (n > capacity()) {T* tmp = new T[n];//memcpy(tmp, _start, len * sizeof(T));for (size_t i = 0; i < len; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + len;_endOfStorage = _start + n;}}vector<string> v;v.push_back("1111");v.push_back("2222");v.push_back("3333");v.push_back("4444");//当T是string等自定义深拷贝容器时,memcpy是浅拷贝,可能会引起内存泄漏甚至程序崩溃//解决,用for直接赋值代替memcpyv.push_back("5555");