一、vector的介绍
1.vector的介绍
- vector是表示可变大小数组的序列容器。
- vector也采用的连续存储空间来存储元素,就是可以采用下标对vector的元素进行访问,和数组一样。
- 它的大小是可以动态改变的。
2.重要的接口组成
二、 vector迭代器的使用
2.1 vector iterator 的使用
void testvector2()
{vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);vector<int>::iterator it = v1.begin(); //普通正向迭代器可以读可以写while (it != v1.end()){*it = *it * 2;cout << *it << " ";it++;}vector<int>::reverse_iterator vit = v1.rbegin(); //reverse逆置 reserve保留while (vit != v1.rend()){cout << *vit << " ";vit++;}cout << endl;for (auto e : v1) //编译器替换成迭代器生成的{cout << e << " ";}cout << endl;
}void print_vector(const vector<int>& v) //传引用,加引用就加const,const 对象就要用const的迭代器
{vector<int>::const_iterator it = v.begin();while (it != v.end()){//*it = *it + 1; const的迭代器不可以写,修改cout << *it << " ";it++;}cout << endl;
}
2.2 vector空间相关函数
在上一章string中我们详细介绍过所以就不去讲解了
但这里我我们要注意一下:
resize:是直接开空间resize(100)是从低一百个位置开始计算
size是100
reserve:是提前开空间,第0个位置
size是0
2.3 vector的增删查改
2.4 find,sort,swap的介绍
参数是一段迭代器区间,在此区间你要添加需要查找的值,找到后返回这个值对应的迭代器位置
若找不到,则返回迭代器last
vector<int> vv{1,2,3,4,5,6,7,8,9};
auto pos = find(vv.begin(),vv.end(),5);
cout<<*pos;
sort函数
他本质就是快排,所以当我们输入一些数的时候,调用迭代器,他会自动排序
vector<int> vv{5,7,3,9,6,4,1,2,8};
sort(vv.begin().vv.end());
swap函数
这里就不过多介绍了,懂得都懂
2.5 空间关系
三、迭代器失效问题
vector底层就是一个指针,vector的迭代器就是原生态指针T*
因此迭代器失效,实际就是迭代器底层对应指针所指向的空间被销毁了,而使用一块已经被释放的空间,造成的后果是程序崩溃(即如果继续使用已经失效的迭代器,程序可能会崩溃)
3.1 使用迭代器区间来构造
在顺序表中存放string类型:
string str("abcdefg");
vector<string> vv(str.begin(),str.end());template <class InputIterator>
vector(InputIterator first, InputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr)
{while (first != last){push_back(*first);++first;}
}
四、深浅拷贝问题
- resize开辟有效数据空间并初始化时不能使用memset初始化,因为mem系列函数是按字节去处理
- reserve开辟容量空间时开辟的新空间不能使用memcpy把旧空间的数据拷贝过去,要使用循环赋值过去,因为memcpy是浅拷贝,浅拷贝最后会导致释放旧空间新空间的指针指向一块已被释放的空间,造成程序崩溃
代码测试:
Vector(const Vector<T>& v)
{assert(v._start && v._finish && v._endofsto);_start = new T[v.capacity()];//给size或capacity都可以memcpy(_start, v._start, sizeof(T) * v.size());
}
解决办法:
Vector(const Vector<T>& v)
{assert(v._start && v._finish && v._endofsto);_start = new T[v.capacity()];//给size或capacity都可以//memcpy(_start, v._start, sizeof(T) * v.size()); //使用memcpy时,数组是二维数组会发生问题for (size_t i = 0; i < size(); i++){_start[i] = v._start[i];_finish = _start + v.size();}_endofsto = _start + v.capacity();
}
五、二维数组的开辟和图解
song::vector<song::vector> vv(n); 构造一个vv动态二维数组,vv中总共有n个元素,每个元素都是vector类型的,每行没有包含任何元素,如果n为5时如下所示
代码总结:
#pragma once
#include<iostream>
#include<vector>
#include<assert.h>
#include<list>using namespace std;template<class T>
class Vector
{
public:typedef T* iterator;typedef const T* const_iterator;void swap(Vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofsto, v._endofsto);}iterator begin(){return _start;}const_iterator begin()const{return _start;}iterator end(){return _finish;}const_iterator end()const{return _finish;}Vector():_start(nullptr), _finish(nullptr), _endofsto(nullptr){}template<class InputIterator>Vector(InputIterator first, InputIterator last)//有迭代器区间的构造:_start(nullptr), _finish(nullptr), _endofsto(nullptr){while (first != last){push_back(*first);first++;}}//这里将size_t改为int可以解决间接寻址的错误,但是库中使用的是size_tVector(int n, const T& val = T())//构造函数:插入n个val,T()是匿名对象的缺省,调用默认构造函数:_start(nullptr), _finish(nullptr), _endofsto(nullptr){reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}~Vector(){delete[] _start;_start = _finish = _endofsto = nullptr;}/*Vector(const Vector<T>& v):_start(nullptr),_finish(nullptr),_endofsto(nullptr){reserve(v.size());for (const auto& e : v){push_back(e);}}*/Vector(const Vector<T>& v){assert(v._start && v._finish && v._endofsto);_start = new T[v.capacity()];//给size或capacity都可以memcpy(_start, v._start, sizeof(T) * v.size()); //使用memcpy时,数组是二维数组会发生问题/*for (size_t i = 0; i < size(); i++){_start[i] = v._start[i];_finish = _start + v.size();}_endofsto = _start + v.capacity();*/}size_t capacity()const{return _endofsto - _start;}size_t size()const{return _finish - _start;}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}//void reserve(size_t n)//{// if (n > capacity())// {// size_t sz = size();// T* tmp = new T[n];// if (_start)// {// memcpy(tmp, _start, sizeof(T) * size());// delete[] _start;// }// _start = tmp;// _finish = _start + sz;// _endofsto = _start + n;//开辟n个空间// }//}void reserve(size_t n){if (n > capacity()){size_t sz = size();T* tmp = new T[n];if (_start){memcpy(tmp, _start, sizeof(T)*sz);/*for (size_t i = 0; i < sz; ++i){tmp[i] = _start[i];}delete[] _start;*/}_start = tmp;_finish = _start + sz;_endofsto = _start + n;}}void resize(size_t n, const T& val = T()){if (n > capacity())//扩容{reserve(n);}if (n > size())//初始化,前面的数据不动,后面添加val{while (_finish < _start + n){*_finish = val;_finish++;}}else if (n <= size())//删除数据,但不改变原先的数据{_finish = _start + n;}}void push_back(const T& x){/*if (_endofsto == _finish){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = x;_finish++;*/insert(end(), x);}void pop_back(){assert(_finish > _start);_finish--;}iterator insert(iterator pos, const T& x)//若不传入地址或引用,发生扩容后,p位置将不在start和finish之间 { //虽然在函数内部修改了pos,但是pos只是p的一份拷贝assert(pos >= _start && pos <= _finish); //库中没有传地址或引用,按照库中的来if (_finish == _endofsto){size_t len = pos - _start;reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + len;//不更新pos位置的话,扩容后,迭代器会失效}iterator end = _finish - 1;while (end >= pos){*(end + 1) = *end;end--;}*pos = x;_finish++;return pos;}iterator erase(iterator pos){assert(pos >= _start && pos < _finish);iterator end = pos;while (end <= _finish){*(end) = *(end + 1);end++;}_finish--;return pos;//if (size() < capacity() / 2)//库中可能是这样实现的,缩容可能会有迭代器失效的问题//{// //缩容//}}Vector<T>& operator=(Vector<T> v)//要交换this和v就不能传引用{swap(v);//交换后,局部变量v销毁时刚好把*this原先的空间给释放掉了return *this;}T& front(){assert(size() > 0);return *_start;}T& back(){assert(size() > 0);return *_finish;}private:iterator _start;iterator _finish;iterator _endofsto;
};
以上就是今天的vector实现,喜欢的话请留下您的支持吧,感谢您的收看