vector
- 1.vector的介绍及使用
- 1.1 vector的介绍
- 1.2 vector的使用
- 1.2.1 vector的定义
- 1.2.2 vector iterator 的使用
- 1.2.3 vector 常用的接口
- 1.2.4 vector 空间增长问题
- 1.2.4 vector 迭代器失效问题。(重点)
- 2.vector模拟实现
1.vector的介绍及使用
1.1 vector的介绍
vector的文档介绍
使用STL的三个境界:能用,明理,能扩展 ,那么下面学习vector,我们也是按照这个方法去学习
1.2 vector的使用
vector学习时一定要学会查看文档:vector的文档介绍,vector在实际中非常的重要,在实际中我们熟悉常见的接口就可以,下面列出了哪些接口是要重点掌握的。
1.2.1 vector的定义
vector的构造代码演示
1.2.2 vector iterator 的使用
1.2.3 vector 常用的接口
size 获取数据个数
capacity 获取容量大小
empty 判断是否为空
resize(重点) 改变vector的size
reserve (重点) 改变vector的capacity
push_back(重点) 尾插
pop_back (重点) 尾删
find 查找。(注意这个是算法模块实现,不是vector的成员接口)
insert 在position之前插入val
erase 删除position位置的数据
swap 交换两个vector的数据空间
operator[] (重点) 像数组一样访问
这些接口使用并不算困难,关键是我们能不能自己造轮子
1.2.4 vector 空间增长问题
测试vector的默认扩容机制
#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<vector>
using namespace std;
void TestVectorExpand()
{size_t sz;vector<int> v;sz = v.capacity();cout << "making v grow:\n";for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}
}int main()
{TestVectorExpand();return 0;
}
如果已经知道了所需空间大小,可以提前开好空间避免频繁扩容
void TestVectorExpandRe()
{vector<int> v;cout << "making v grow:\n";size_t sz = 100;v.reserve(100);bool change = false;for (int i = 0; i < 100; ++i){v.push_back(i);if (sz != v.capacity()){change = true;sz = v.capacity();cout << "capacity changed: " << sz << '\n';}}if (!change){cout << "Not change" << endl;}
}
1.2.4 vector 迭代器失效问题。(重点)
迭代器的主要作用就是让算法能够不用关心底层数据结构,其底层实际就是一个指针,或者是对
指针进行了封装,比如:vector的迭代器就是原生态指针T* 。因此迭代器失效,实际就是迭代器
底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即
如果继续使用已经失效的迭代器,程序可能会崩溃)。
对于vector可能会导致其迭代器失效的操作有:
-
- 会引起其底层空间改变的操作,都有可能是迭代器失效,比如:resize、reserve、insert、assign、push_back等。
it一开始指向的空间已经被销毁了,程序会崩。及时更新迭代器
-
- 指定位置元素的删除操作–erase
#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1, 2, 3, 4 };auto it = v.begin();while (it != v.end()){if (*it % 2 == 0)v.erase(it);++it;}return 0;
}
这段代码会很好解释为什么删除也会有迭代器失效的问题
我们期望指向2的lterator指向了3,迭代器失效了它的指向不符合我们的预期
2.vector模拟实现
std::vector的核心框架接口的模拟实现bit::vector
实现代码
#pragma once
#include<assert.h>
#include<list>
#include<string>namespace Yusei
{template<class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;// C++11 前置生成默认构造vector() = default;//默认构造函数走初始化列表,成员变量声明了缺省值vector(const vector<T>& v)//拷贝构造{reserve(v.size());for (auto& e : v){push_back(e);}}// 类模板的成员函数,还可以继续是函数模版template <class InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);++first;}}vector(size_t n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}vector(int n, const T& val = T()){reserve(n);for (int i = 0; i < n; i++){push_back(val);}}void clear(){_finish = _start;}// v1 = v3vector<T>& operator=(const vector<T>& v){if (this != &v){clear();reserve(v.size());for (auto& e : v){push_back(e);}}return *this;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}// v1 = v3//vector& operator=(vector v)vector<T>& operator=(vector<T> v){swap(v);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin() const{return _start;}const_iterator end() const{return _finish;}void reserve(size_t n){if (n > capacity){size_t oldsize = size();iterator tmp = new iterator[n];for (size_t i=0;i<oldsize;i++){tmp[i] = _start[i];}delete[]_start;_start = _finish = _end_of_storage = nullptr;_start = tmp;_finish = tmp + oldsize;_end_of_storage = tmp + n;}}void resize(size_t n, T val = T()){if (n < size()){_finish = _start + n;}else{reserve(n);for (size_t i = size(); i < n; i++){_start[i] = val;}}}size_t size() const{return _finish - _start;}size_t capacity() const{return _end_of_storage - _start;}bool empty() const{return _start == _finish;}void push_back(const T& x){// 扩容if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : capacity() * 2);}*_finish = x;++_finish;}void pop_back(){assert(!empty());--_finish;}iterator insert(iterator pos, const T& x){assert(pos >= _start);assert(pos <= _finish);// 扩容if (_finish == _end_of_storage){size_t len = _finish - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;--end;}*pos = x;++_finish;return pos;}iterator erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it != end()){*(it - 1) = *it;++it;}--_finish;return pos;}T& operator[](size_t i){assert(i < size());return _start[i];}const T& operator[](size_t i) const{assert(i < size());return _start[i];}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};
}
测试代码
#define _CRT_SECURE_NO_WARNINGS 1
#include"vector.h"
#include<iostream>
using namespace Yusei;
using std::endl;
using std::cout;
using std::cin;
using std::string;
using std::list;
template<class T>
void print_vector(const vector<T>& v)
{// 规定,没有实例化的类模板里面取东西,编译器不能区分这里const_iterator// 是类型还是静态成员变量//typename vector<T>::const_iterator it = v.begin();auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;
}template<class Container>
void print_container(const Container& v)
{/*auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;*/for (auto e : v){cout << e << " ";}cout << endl;
}void test_vector1()
{vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;vector<int>::iterator it = v.begin();while (it != v.end()){std::cout << *it << " ";++it;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;print_vector(v);vector<double> vd;vd.push_back(1.1);vd.push_back(2.1);vd.push_back(3.1);vd.push_back(4.1);vd.push_back(5.1);print_vector(vd);
}void test_vector2()
{std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);print_container(v);/*v.insert(v.begin() + 2, 30);print_vector(v);*/int x;cin >> x;auto p = find(v.begin(), v.end(), x);if (p != v.end()){// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值/*v.insert(p, 20);(*p) *= 10;*/p = v.insert(p, 40);(*(p + 1)) *= 10;}print_container(v);
}void test_vector3()
{std::vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);print_container(v);// 删除所有的偶数auto it = v.begin();while (it != v.end()){if (*it % 2 == 0){it = v.erase(it);}else{++it;}}print_container(v);
}void test_vector4()
{int i = int();int j = int(1);int k(2);vector<int> v;v.resize(10, 1);v.reserve(20);print_container(v);cout << v.size() << endl;cout << v.capacity() << endl;v.resize(15, 2);print_container(v);v.resize(25, 3);print_container(v);v.resize(5);print_container(v);
}void test_vector5()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);print_container(v1);vector<int> v2 = v1;print_container(v2);vector<int> v3;v3.push_back(10);v3.push_back(20);v3.push_back(30);v1 = v3;print_container(v1);print_container(v3);
}void test_vector6()
{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(4);vector<int> v2(v1.begin(), v1.begin() + 3);print_container(v1);print_container(v2);list<int> lt;lt.push_back(10);lt.push_back(10);lt.push_back(10);lt.push_back(10);vector<int> v3(lt.begin(), lt.end());print_container(lt);print_container(v2);vector<string> v4(10, "1111111");print_container(v4);vector<int> v5(10);print_container(v5);vector<int> v6((size_t)10, 1);print_container(v6);vector<int> v7(10, 1);print_container(v7);
}void test_vector7()
{vector<string> v;v.push_back("11111111111111111111");v.push_back("11111111111111111111");v.push_back("11111111111111111111");v.push_back("11111111111111111111");print_container(v);v.push_back("11111111111111111111");print_container(v);
}