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

[C++进阶篇]STL中vector的使用

一、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实现,喜欢的话请留下您的支持吧,感谢您的收看



 

相关文章:

  • 【亚马逊云科技产品测评】活动征文|亚马逊云科技AWS之EC2详细测评
  • 【Leetcode】【消失的数字】【C语言】
  • 浅谈前端出现率高的设计模式
  • linux的另一种判断符号【中括号】
  • 使用udevdm查询蓝牙模块的信息
  • K8S知识点(三)
  • Springboot学生就业信息管理系统-计算机毕设 附源码95340
  • 【C语言基础入门】二级指针、一维数组与指针、二维数组与指针
  • 软通杯算法竞赛--周赛题目(一)
  • 【微服务】mysql + elasticsearch数据双写设计与实现
  • 艺术的维度:洞察AI诈骗,优雅防范之艺术
  • C++构造函数
  • docker 下安装mysql8.0
  • ROS学习笔记(4):ROS架构和通讯机制
  • 大数据毕业设计选题推荐-热门旅游景点数据分析-Hadoop-Spark-Hive
  • [译]CSS 居中(Center)方法大合集
  • C++类的相互关联
  • MQ框架的比较
  • Python连接Oracle
  • vue总结
  • 表单中readonly的input等标签,禁止光标进入(focus)的几种方式
  • 持续集成与持续部署宝典Part 2:创建持续集成流水线
  • 基于Volley网络库实现加载多种网络图片(包括GIF动态图片、圆形图片、普通图片)...
  • 开放才能进步!Angular和Wijmo一起走过的日子
  • 前端自动化解决方案
  • 如何利用MongoDB打造TOP榜小程序
  • 运行时添加log4j2的appender
  • 湖北分布式智能数据采集方法有哪些?
  • ###51单片机学习(2)-----如何通过C语言运用延时函数设计LED流水灯
  • #{}和${}的区别?
  • #100天计划# 2013年9月29日
  • (HAL)STM32F103C6T8——软件模拟I2C驱动0.96寸OLED屏幕
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (Matlab)遗传算法优化的BP神经网络实现回归预测
  • (附源码)ssm基于web技术的医务志愿者管理系统 毕业设计 100910
  • (三)模仿学习-Action数据的模仿
  • (转)ObjectiveC 深浅拷贝学习
  • * 论文笔记 【Wide Deep Learning for Recommender Systems】
  • .【机器学习】隐马尔可夫模型(Hidden Markov Model,HMM)
  • .bat批处理(十一):替换字符串中包含百分号%的子串
  • .helper勒索病毒的最新威胁:如何恢复您的数据?
  • .net core webapi 大文件上传到wwwroot文件夹
  • .NET LINQ 通常分 Syntax Query 和Syntax Method
  • .net 托管代码与非托管代码
  • .NET是什么
  • .net与java建立WebService再互相调用
  • /var/lib/dpkg/lock 锁定问题
  • []AT 指令 收发短信和GPRS上网 SIM508/548
  • [100天算法】-x 的平方根(day 61)
  • [Angular] 笔记 7:模块
  • [C#]winform使用引导APSF和梯度自适应卷积增强夜间雾图像的可见性算法实现夜间雾霾图像的可见度增强
  • [C#基础知识系列]专题十七:深入理解动态类型
  • [C++]C++类基本语法
  • [Enterprise Library]调用Enterprise Library时出现的错误事件之关闭办法
  • [G-CS-MR.PS02] 機巧之形2: Ruler Circle