文章目录

  • 前言:
  • vector与数组
  • 迭代器---“通用指针"
    • 迭代器的本质
    • 迭代器的分类
    • 迭代器失效
  • vector功能复写
    • 成员变量
    • 构造函数
      • 默认构造函数
      • 自定义的构造函数
      • 拷贝构造函数
      • 赋值运算符
    • size()
    • capacity()
    • operator[]
    • begin()
    • end()
    • reserve()
    • resize()
    • push_back()
    • pos_back()
    • insert()
    • erase()
    • find()
  • 全部代码

前言:

  • 博主收集的资料New Young,连载中。
  • 博主收录的问题:New Young
  • 转载请标明出处:New Young

vector与数组

vector在底层是一种类似数组的C++类模板,因此vector容器一但实例化其大小是不变的,但是容器中指向堆上的元素对象是动态变化的,支持“增删查改",同数组一样对于插入,insert的效率是很低的

迭代器—“通用指针"

迭代器的本质

  1. 循环的控制方式有2种:标志控制(while),计数控制(for),而迭代器将这2种循环方式的统一为一种控制方式—迭代器控制—“通用指针"
  2. 为什么称迭代器为指针,因为其的行为和指针非常相似,另外不同容器的迭代器类型是不同的,因此这里的“通用"是一种概念上的通用
  3. 几乎所有的的泛型容器和泛型算法都使用迭代器来访问对象

迭代器的分类

迭代器 功能
Input_iterator–输入迭代器 只提高读操作
Output_iterator–输出迭代器 只提高写操作
Forward_iterator–单向迭代器 只能向前访问下一元素,不能向后访问,支持++
Bidirectional_iterator–双向迭代器 双向访问迭代器,支持++与–
Random_iterator–随机迭代器 可以随机访问对象中的每一个元素,支持++,-,+,–等运算

从表中可以得出,功能更全的迭代器是支持向功能少的迭代器支持的接口进行传参的

迭代器失效

  1. 迭代器失效指的是:当容器底层发生变化,原来的迭代器可能由于元素存储位置的变动,成为野指针或者后续的迭代器不在指向准确的数据。

  2. 常见的引发操作:insert()时的扩容,erase()的缩容,clear(),remove()等

  3. 解决方法:及时的更新迭代器并通过返回值得到正确的指向下一个元素的

vector功能复写

成员变量

typedef T* iterator;
iterator _start;
iterator _finish;
iterator _end_of_storage;

构造函数

默认构造函数

vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}

自定义的构造函数

vector支持通过迭代器区间来初始化对象

 template<class inputIterator>vector(inputIterator first, inputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);++first;}}

拷贝构造函数

vector(const vector<T>& v)//提前初始化成员,防止delete随机值: _start(nullptr),_finish(nullptr),_end_of_storage(nullptr){vector<T> tmp(v.begin(), v.end());std::swap(_start, tmp._start);std::swap(_finish, tmp._finish);std::swap(_end_of_storage, tmp._end_of_storage);}

赋值运算符

 //现代写法vector<T>& operator=(vector<T>v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}

size()

size_t size()const{return _finish - _start;}

capacity()

size_t capacity()const{return _end_of_storage - _start;}

operator[]

T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const {assert(pos < size());return _start[pos];}

begin()

typedef T* iterator;iterator begin(){return _start;}
typedef T* const_iterator;const_iterator begin()const{return _start;}

end()

typedef T* iterator;
iterator end(){return _finish;}
typedef T* const_iterator;
const_iterator end()const{return _finish;}

reserve()

void reserve(size_t n){if (n > capacity()){T* tmp = new T[n];int sz = size();if (_start != nullptr){//使用memcpy会导致浅拷贝野指针问题//memcpy(tmp, _start, sizeof(T)*sz);//使用深拷贝赋值// 或者定位newfor (size_t i = 0; i < sz; ++i){//调用深拷贝的赋值函数tmp[i] = _start[i];}delete[]_start;}_start = tmp;//注意这里要用旧的size,因为_start改变时,//finish未变,直接使用size(),可能会出现负的情况_finish = _start + sz;_end_of_storage = _start + n;}}

resize()

编译器对很多类型包括内置类型都将它们进行了提升,类似一种类,因此int()=0;

 void resize(size_t n, const T& value = T()){if (n < size()){_finish = _start + n;}else{if (n > capacity()){reserve(n);}//初始化大于size()的空间for (size_t i =  size(); i < n; ++i){_start[i]  = value;}_finish = _start + n;_end_of_storage = _start + n;}}

push_back()

void push_back(const T& value){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = value;++_finish;}

pos_back()

void pop_back(){assert(_finish > _start);--_finish;}

insert()

如果inisrt中发生了扩容导致pos指向的空间被释放
又pos本身是一个指针,这就成了对野指针的操作是非法的----迭代器失效

iterator  insert(iterator  pos,const T& value){assert(pos >= _start);assert(pos <= _finish);//扩容会导致pos失效,需要更新posif (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ?  4 : 2 * capacity());pos = _start + len;}iterator end = _finish;while (end > pos){*(end) = *(end - 1);--end;}*pos = value;++_finish;return pos;}

erase()

 //不同版本的erase可能会 异地 缩容,因此要返回一个iterator erase(iterator  pos){assert(pos >= _start);assert(pos < _finish);iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *(begin);++begin;}--_finish;return pos;}

find()

template<class InputIterator, class T>InputIterator find (InputIterator first, InputIterator last, const T& val)
{while (first!=last) {if (*first==val) return first;++first;}return last;
}

全部代码

Vector.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include <stdlib.h>
#include <string>
#include <assert.h>
#include<time.h>
#include<windows.h>
#include<algorithm>
#include<vector>namespace My_Vet
{
template <class T>
class vector
{
public:typedef T* iterator;iterator begin(){return _start;}iterator end(){return _finish;}typedef T* const_iterator;const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}vector():_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){}//传统写法/*vector(const vector<T>& v){T* tmp = new <T>[v.size()*sizeof(T)];delete[]_start;_start = tmp;_finish = tmp + v.size();_end_of_storage = tmp + v.capacity();//传统写法要考虑浅拷贝问题//memcpy(_start, v._start, sizeof(T)*v.size());for(size_t i =0;i<sz;++i){_start[i]=v._start[i];}}*///现在写法//因为vector只有默认的构造函数,无自定义构造函数,因此需要自定义构造函数// template<class inputIterator>vector(inputIterator first, inputIterator last):_start(nullptr), _finish(nullptr), _end_of_storage(nullptr){while (first != last){push_back(*first);++first;}}vector(const vector<T>& v)//提前初始化成员,防止delete随机值: _start(nullptr),_finish(nullptr),_end_of_storage(nullptr){vector<T> tmp(v.begin(), v.end());std::swap(_start, tmp._start);std::swap(_finish, tmp._finish);std::swap(_end_of_storage, tmp._end_of_storage);}//现代写法vector<T>& operator=(vector<T>v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_end_of_storage, v._end_of_storage);}size_t size()const{return _finish - _start;}size_t capacity()const{return _end_of_storage - _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()){T* tmp = new T[n];int sz = size();if (_start != nullptr){//使用memcpy会导致浅拷贝野指针问题//memcpy(tmp, _start, sizeof(T)*sz);//使用深拷贝赋值// 或者定位newfor (size_t i = 0; i < sz; ++i){//调用深拷贝的赋值函数tmp[i] = _start[i];}delete[]_start;}_start = tmp;//注意这里要用旧的size,因为_start改变时,//finish未变,直接使用size(),可能会出现负的情况_finish = _start + sz;_end_of_storage = _start + n;}}//编译器对很多类型包括内置类型都将它们进行了提升,类似一种类,因此int()=0;void resize(size_t n, const T& value = T()){if (n < size()){_finish = _start + n;}else{if (n > capacity()){reserve(n);}//初始化大于size()的空间for (size_t i =  size(); i < n; ++i){_start[i]  = value;}_finish = _start + n;_end_of_storage = _start + n;}}void push_back(const T& value){if (_finish == _end_of_storage){reserve(capacity() == 0 ? 4 : 2 * capacity());}*_finish = value;++_finish;}void pop_back(){assert(_finish > _start);--_finish;}//如果inisrt中发生了扩容导致pos指向的空间被释放//又pos本身是一个指针,这就成了对野指针的操作是非法的----迭代器失效iterator  insert(iterator  pos,const T& value){assert(pos >= _start);assert(pos <= _finish);//扩容会导致pos失效,需要更新posif (_finish == _end_of_storage){size_t len = pos - _start;reserve(capacity() == 0 ?  4 : 2 * capacity());pos = _start + len;}iterator end = _finish;while (end > pos){*(end) = *(end - 1);--end;}*pos = value;++_finish;return pos;}//不同版本的erase可能会 异地 缩容,因此要返回一个iterator erase(iterator  pos){assert(pos >= _start);assert(pos < _finish);iterator begin = pos + 1;while (begin < _finish){*(begin - 1) = *(begin);++begin;}--_finish;return pos;}~vector(){delete[]_start;_start = _finish = _end_of_storage = nullptr;//std::cout << "~vector()" << std::endl;}//iterator find()//{////}private:iterator _start;iterator _finish;iterator _end_of_storage;};
}

STL——vector与迭代器相关推荐

  1. C++ stl vector介绍

    转自: STL vector用法介绍 介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if ...

  2. c++ vector 先进先出_C++ STL Vector(容器)学习

    本文参考博客链接及书籍: 侯捷老师的<STL 源码剖析> 在C++标准库中,STL容器是一些常用数据结构的实现,比如数组.链表.树.栈.队列.散列表.集合.映射表等,可以分为序列式(seq ...

  3. STL vector的几种清空容器(删除)办法

    1.为什么需要主动释放vector内存 来自 <https://blog.csdn.net/hellokandy/article/details/78500067> vector其中一个特 ...

  4. STL vector 容器介绍

    介绍 这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用.通 ...

  5. STL vector的erase操作问题

    STL vector的erase操作问题 一老大说CSDN上有篇博文("关于STL vector的erase操作",地址是:http://blog.csdn.net/tingya/ ...

  6. STL vector容器

    介绍  这篇文章的目的是为了介绍std::vector,如何恰当地使用它们的成员函数等操作.本文中还讨论了条件函数和函数指针在迭代算法中使用,如在remove_if()和for_each()中的使用. ...

  7. stl vector 函数_在C ++ STL中使用vector :: begin()和vector :: end()函数打印矢量的所有元素...

    stl vector 函数 打印向量的所有元素 (Printing all elements of a vector) To print all elements of a vector, we ca ...

  8. stl vector 函数_vector :: crend()函数以及C ++ STL中的示例

    stl vector 函数 C ++ vector :: crend()函数 (C++ vector::crend() function) vector::crend() is a library f ...

  9. STL 容器和迭代器连载6_顺序容器的操作3

    2019独角兽企业重金招聘Python工程师标准>>> /*- ========================================================== ...

最新文章

  1. android里的editText怎么用,Android自定义控件EditText使用详解
  2. python 图像计算方位角
  3. Leetcode 67. 二进制求和 (每日一题 20210826)
  4. shell 打印追加_[转]shell 数组定义、使用和追加
  5. englishpod主持人对话文本_Englishpod 69 | 主持人文本讲解 | How Would You Like Your Eggs?...
  6. [react] 在react中无状态组件有什么运用场景
  7. console对象的方法log、info、warn、error的区别及几个实用的方法
  8. Springboot之actuator配置不当漏洞(autoconfig、configprops、beans、dump、env、health、info、mappings、metrics、trace)
  9. 【算法学习】B-Tree编程实现(C++模板类封装)
  10. 简单的ios网络数据交互
  11. 一个关于文件结构体数组的条件排序函数
  12. 计算并输出1000以内的所有“完数”之和
  13. doc转docx文件会乱吗_利用python将doc文件转换为docx
  14. 区分指针数组和数组指针
  15. 10道经典java面试题_实习生必问(java基础)
  16. 管道—过滤器简介 软件体系结构
  17. QQ群邮件批量群发源码
  18. Web前端知识点总结(持续更新中...)
  19. 2012年8月30日
  20. “peter piper picked a peck of pickled peppers“统计这段绕口令有多少个以p开头的单词 String中方法:split/startWith

热门文章

  1. 华为rstp配置实例
  2. 堪比N6705和Power Monitor AAA10F 的高精度_高采样率_低功耗测试电源mPower1203
  3. 促双碳|智慧能源管理解决方案
  4. Matlab读取和显示图像
  5. excel 中插入文件
  6. 渣土车识别YOLOv5
  7. 2019-10-16 博客热门文章
  8. 【Vuejs】1454- 深入了解 vue-cli
  9. rufus制作ubuntuU盘启动以及window10和ubuntu20.04.2双系统
  10. 蓝牙降噪耳机哪个比较好?四大热门降噪蓝牙耳机推荐