当前位置: 首页 > news >正文

vector使用模拟实现

vector使用&模拟实现

  • 1.vector拷贝构造
  • 2.其它接口
  • 3、vector模拟实现

1.vector拷贝构造

alt
alt
alt
al
 vector使用如下:
vector是一个存储数据的顺序表。push_back进行插入数据,vector是模版定义的,可以存储任何数据:vector<数据类型>变量名;

void test_vector1()
{//string //vector<char> //vector<string> v3;vector<double> v2;vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;//在vector中定义的,要指明来处vector<int> :: iterator it1 = v1.begin();while (it1 != v1.end()){cout << (*it1) << " ";it1++;}cout << endl;for (auto e : v1){cout << e << " ";}cout << endl;
}

2.其它接口


 operator=是赋值
alt
 begin、end是迭代器
alt

 size:获取数据个数 capacity:获取容量
 resize:指定数据个数 reserve:设置容量

alt
 operator[]:按下标访问数据
 front:获得第一个数据
 back:获得最后一个数据

alt
alt
alt
 push_back尾插,pop_back尾删
alt
alt

 insert在某个地址插入数据,其他数据向后面移动,注意的是用迭代器传参

//void push_back(const string& s)
//{}
void test_vector2()
{vector<string> v1;string s1("张三");v1.push_back(s1);v1.push_back(string("李四"));v1.push_back("王五");v1[0] += "猪";for (const auto& e : v1){cout << e << " ";}cout << endl;cout << v1.front() << endl;cout << v1.back() << endl;
}void test_vector3()
{vector<int> v1;v1.push_back(10);v1.push_back(2);v1.push_back(30);v1.push_back(4);v1.push_back(44);v1.push_back(4);v1.push_back(40);v1.push_back(4);//仿函数greater<int> gt;//默认是升序//传gt,降序,具体为什么,不知道//sort(v1.begin(), v1.end(),gt);// 一般这么用//greater<int>() -->传匿名对象sort(v1.begin(), v1.end(), greater<int>());//sort(v1.begin(), v1.begin() + v1.size() / 2);for (auto e : v1){cout << e << " ";}
}

alt
 sort(RandomAccessIterator first,RandomAccessIterator last,Compare comp)
 sort默认是排升序,传迭代器进行排序,若排降序,则用仿函数greater<数据类型>,可以传匿名对象,greaterv< int >()
alt
 find在算法中可查找任何一个数据的迭代器
、alt

3、vector模拟实现

alt
 基本框架如下: _star指向第一个位置,_finish指向存储数据的下一个位置,这样_finish-_start就是数据个数,_end_of_storage申请一段空间的最后一个字节的下一个位置,_end_of_storage-_start就是整个空间的容量

namespace wyj
{template<class T>class vector{public:typedef T* iterator;typedef const T*  const_iterator;private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};
}

 先把_start,_finish,_end_of_storage置nullptr,调用默认构造时,会初始化成员会nullptr,在写push_back,要尾插,在写一些预备接口,capacity,size,reserve.具体如下。

iterator begin()
{return _start;
}iterator end()
{return _finish;
}const_iterator begin()const
{return _start;
}const_iterator end()const
{return _finish;
}
size_t size()const
{return _finish - _start;
}size_t capacity()const
{return _end_of_storage - _start;
}T& operator[](size_t i)
{return _start[i];
}const T& operator[](size_t i)const
{return _start[i];
}void reserve(size_t n)
{if (capacity() < n){//这儿是使用迭代器(指针)来标记位置//只要申请新的空间,空间地址就会变了//因此先存储_start到_finish的距离size_t old_size = size();T* tmp = new T[n];if (_start){//memcpy不能传nullptrmemcpy(tmp, _start, sizeof(T) * n);delete[] _start;}_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}
}

 具体上面接口如下,简单的接口不做解释,看看reserve还是那一套,先申请一个指定的空间,把内容拷贝到指定空间,在更新成员变量即可,需要注意的是,上面写法不行,浅拷贝可以,深拷贝不行,假设存储vector < string> v1,存的是string,再扩容时,发生浅拷贝,只是把string里面成员的值拷贝过来,真正字符串在堆上存的空间已经调用析构函数销毁了,这个是不行的,只有赋值调用string的拷贝构造才行。

 写push_back、pop_back

//这儿插入的时候参数为const T& val,考虑到自定义类型,数据过大
void push_back(const T& val)
{if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reserve(newcapacity);}*_finish = val;_finish++;
}void pop_back()
{assert(size() > 0);--_finish;
}

 写insert、erase

iterator insert(iterator pos,const T& val)
{assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){//扩容有问题,导致pos地址会变化size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reserve(newcapacity);pos = _start + len;}iterator end = _finish;while (end > pos){*end = *(end - 1);end--;}*pos = val;++_finish;return pos;
}void erase(iterator pos)
{assert(pos >= _start && pos < _finish);iterator end = pos + 1;while (end != _finish){*(end - 1) = *end;++end;}_finish--;
}

alt

 iterator insert(iterator pos,const T& val),在插入数据的时候发生扩容,导致pos地址发生变化,在函数外面出来时,访问pos位置,原来pos地址所在的空间已销毁,要更新pos,因此返回pos的地址,来更新pos,所谓的迭代器失效问题。
 还有erase问题,一些编译器出于安全考虑,删除的位置,将不会被访问,这也是迭代器失效的一种。
 测试代码如下

void test3()
{vector<int>v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);//删除2,先记住2的地址vector<int> ::iterator it = v1.begin() + 1;v1.erase(it);//在访问保存的这个地址cout << (*it) << endl;
}

alt

 构造函数接口如下

template<class InputItrator>
vector(InputItrator first, InputItrator 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++){this->push_back(val);}
}vector(int n, const T& val = T())
{reserve(n);for (size_t i = 0; i < n; i++){this->push_back(val);}
}vector(const vector<T>& v)
{reserve(v.size());for (size_t i = 0; i < v.size(); i++){this->push_back(v[i]);}
}vector(initializer_list<T> il)
{reserve(il.size());for (auto& e : il){push_back(e);}
}void swap(vector<T>&v)
{std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);
}
//强制默认构造
vector() = default;
~vector()
{if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}
}//v是一份临时拷贝
vector<T>& operator=( vector<T>v)
{this->swap(v);return *this;
}

 先写拷贝构造,vector(const vector& v)取v的元素直接尾插即可。
 支持迭代器的构造函数,用模版来写,初始化时,直接可以放任何迭代器访问的数据。
template < class InputItrator>
vector(InputItrator first, InputItrator last)

 介绍下下面这个构造函数
alt
alt
alt
 关于template< class T>class initializer_list的详细介绍看这个博客!
 <initializer_list> 头文件中的一个模板类。它可以用于接收花括号初始化列表(例如 {1, 2, 3})作为参数。

#include <initializer_list>
#include <iostream>void print(std::initializer_list<int> ilist) {for (auto elem : ilist) {std::cout << elem << ' ';}std::cout << std::endl;
}int main() {print({1, 2, 3, 4, 5}); // 输出:1 2 3 4 5return 0;
}

  用于表示某种特定类型的值的数组,和vector一样,initializer_list也是一种模板类型。
 反正怎么说,initializer_list可以看做能存储任何数据类型的模版数组。

#define  _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include <iostream>
#include <algorithm>
#include <assert.h>
using namespace std;namespace wyj
{template<class T>class vector{public:typedef T* iterator;typedef const T*  const_iterator;iterator begin(){return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}size_t size()const{return _finish - _start;}size_t capacity()const{return _end_of_storage - _start;}T& operator[](size_t i){return _start[i];}const T& operator[](size_t i)const{return _start[i];}template<class InputItrator>vector(InputItrator first, InputItrator 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++){this->push_back(val);}}vector(int n, const T& val = T()){reserve(n);for (size_t i = 0; i < n; i++){this->push_back(val);}}vector(const vector<T>& v){reserve(v.size());for (size_t i = 0; i < v.size(); i++){this->push_back(v[i]);}}vector(initializer_list<T> il){reserve(il.size());for (auto& e : il){push_back(e);}}void swap(vector<T>&v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}//强制默认构造vector() = default;~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}//v是一份临时拷贝vector<T>& operator=( vector<T>v){this->swap(v);return *this;}void reserve(size_t n){if (capacity() < n){size_t old_size = size();T* tmp = new T[n];if (_start){//memcpy不能传nullptrmemcpy(tmp, _start, sizeof(T) * n);delete[] _start;}_start = tmp;_finish = _start + old_size;_end_of_storage = _start + n;}}//这儿插入的时候参数为const T& val,考虑到自定义类型,数据过大void push_back(const T& val){if (_finish == _end_of_storage){size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reserve(newcapacity);}*_finish = val;_finish++;}void pop_back(){assert(size() > 0);--_finish;}iterator insert(iterator pos,const T& val){assert(pos >= _start && pos <= _finish);if (_finish == _end_of_storage){//扩容有问题,导致pos地址会变化size_t len = pos - _start;size_t newcapacity = capacity() == 0 ? 4 : 2 * capacity();reserve(newcapacity);pos = _start + len;}iterator end = _finish;while (end > pos){*end = *(end - 1);end--;}*pos = val;++_finish;return pos;}void erase(iterator pos){assert(pos >= _start && pos < _finish);iterator end = pos + 1;while (end != _finish){*(end - 1) = *end;++end;}_finish--;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage= nullptr;};void vector_test1(){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);for (size_t i = 0; i < v1.size(); i++){cout << v1[i] << " ";}cout << endl;for (auto e : v1){cout << e << " ";}cout << endl;v1.pop_back();for (auto e : v1){cout << e << " ";}cout << endl;v1.insert(v1.begin(), 0);v1.insert(v1.begin(), -1);for (auto e : v1){cout << e << " ";}cout << endl;v1.erase(v1.begin());for (auto e : v1){cout << e << " ";}cout << endl;vector<int>v2 = v1;for (auto e : v2){cout << e << " ";}cout << endl;}void vector_test2(){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);vector<int>v2(v1.begin(), v1.end()-1);for (auto e : v2){cout << e << " ";}cout << endl;vector<string>v3(3, "hello ");for (auto e : v3){cout << e << " ";}cout << endl;vector<string>v4;v4 = v3;for (auto e : v3){cout << e << " ";}cout << endl;vector<int>v5(2, 1);for (auto e : v5){cout << e << " ";}cout << endl;}void vector_test3(){vector<int>v1 = { 1,2,3,4,5 };for (auto e : v1){cout << e << " ";}cout << endl;}
}


http://www.lryc.cn/news/612444.html

相关文章:

  • Linux 学习 之 killer 问题
  • Unity笔记(三)——父子关系、坐标转换、Input、屏幕
  • STM32学习笔记3-GPIO输入部分
  • 【模电笔记】—— 直流稳压电源——稳压电路
  • RK3568笔记九十六:多路实时目标检测
  • Python应用指南:获取风闻评论数据并解读其背后的情感倾向(二)
  • 【补题】CodeTON Round 1 (Div. 1 + Div. 2, Rated, Prizes!) D. K-good
  • 基于单片机GD32E103的HID按键问题分析
  • hive专题面试总结2
  • 一、Envoy基础概念学习
  • 8.6笔记
  • 《嵌入式数据结构笔记(四):栈结构与队结构链表》
  • Chrontel【7322BMF】CH7322B HDMI Consumer Electronics Control (CEC) devices
  • GaussDB 数据库架构师修炼(六)-3 集群工具管理-主备倒换
  • prometheus+Grafana 监控中间件项目
  • 202506 电子学会青少年等级考试机器人四级实际操作真题
  • 架构层防护在高并发场景下的实践
  • 机器学习-LinearRegression
  • 机器学习模型调优实战指南
  • 机器学习——SVM
  • 居家养老场景下摔倒识别准确率提升 29%:陌讯动态姿态建模算法实战解析
  • 第五十一章:AI模型服务的“百变面孔”:WebUI/CLI/脚本部署全解析
  • 从原理图到PCB的布局
  • LiveQing视频RTMP推流视频点播服务功能-云端录像支持按时间段下载录像时间段下载视频mp4
  • STM32的PWR
  • 引领GameFi 2.0新范式:D.Plan携手顶级财经媒体启动“龙珠创意秀”
  • ZYNQ实现FFT信号处理项目
  • Python科学计算:从基础到工程仿真的完整指南
  • 指挥中心自动化的演变
  • cygwin+php教程(swoole扩展+redis扩展)