vector的底层与使用

前言:vector是顺序表(本质也是数组)

文档参考网站:https://legacy.cplusplus.com/reference/vector/vector/vector/

//底层代码
#include<assert.h>
#include<iostream>
#include<vector>
#include<string>
using namespace std;
namespace bit
{template<typename T>class vector{public:typedef T* iterator;typedef const T* const_iterator;template <typename InputIterator>vector(InputIterator first, InputIterator last){reserve(last - first);while (first != last){push_back(*first);first++;}}vector(int size = 1){_begin = _end = new T[size];_endofstorage = _begin + size;}~vector(){delete[] _begin;_begin = _end = _endofstorage = nullptr;}vector(const vector<T>& s){reserve(s.capacity());for (auto& e : s)push_back(e);}int size() const{return _end - _begin;}int capacity() const{return _endofstorage - _begin;}void reserve(int newcapacity){if (newcapacity > capacity()){int old_size = size();iterator tmp = new T[newcapacity];for(int i = 0 ; i < old_size ; i++){tmp[i] = _begin[i];}//不能用memcpy,防止数据进行浅拷贝_begin = tmp;_end = tmp + old_size;_endofstorage = tmp + newcapacity;}}void push_back(T val){int old_size = size();if (_end == _endofstorage){reserve(2 * old_size);}*_end = val;_end++;}iterator begin() //返回临时变量{return _begin;}iterator end(){return _end;}const_iterator begin() const{return (const_iterator)_begin;}const_iterator end() const {return (const_iterator)_end;}void pop_back(){_end--;}iterator insert(iterator position, const T& val){assert(position < _end);iterator tmp = _end;if (_end == _endofstorage) {size_t len = position - _begin;reserve(2 * size());position = _begin + len;}while (_end != position){*_end = *(_end - 1);_end--;}iterator k = _end;*_end = val;_end = tmp;_end++;return k;}T& operator[] (int n){assert(n < size());return _begin[n];}const T& operator[] (int n) const{assert(n < size());return _begin[n];}iterator erase(iterator position){assert(position < _end);iterator tmp = position;while (position != _end){*(position) = *(position + 1);position++;}_end--;return tmp;}iterator erase(iterator first, iterator last){assert(last < _end && first < _end);int a = last - first;iterator tmp = last;iterator k = first;while (tmp != _end){*first = *tmp;tmp++;first++;}_end -= a;return k;}void clear(){_end = _begin;}void resize(int n, const T& val = T()){int _size = size();if (n > _size){reserve(n);iterator t = _begin + n;while (_end != t){*_end = val;_end++;}}else{_end = _begin + n;}}private:iterator _begin = nullptr;//初始化列表iterator _end = nulptr;iterator _endofstorage;};
}

构造函数

第一种方式: vector( int size = 1 )// 全缺省,作为默然构造函数

 开10个整形的数组

第二个方式:vector( int size , const T& val = T() )

解释 T()        当T为自定义类型时,调用T的默然构造函数

                      但对于内置类型,编译器会自动调用内置类型的默然构造(纯粹为了符合类模版)

                       对于int 为 0  , 对于double 为 0.0 ,对于char 为 '\0' , 对于指针为nullptr等

第三种方式:运用类成员函数模版

template <class InputIterator>vector (InputIterator first, InputIterator last) 左闭右开

第四种方式:C++11提出的(用初始化链表初始化)

  

e的类型是初始化链表

初始化链表只有四个接口函数 , 初始化链表只能支持遍历 ,不能支持赋值,初始化链表中的数据储存在常量区中(不能被修改)

析构函数

底层实现简单  ( clear 函数 + 指针置为空指针 )

这里补充一下clear函数

void clear()
{

_end = _begin;

}

~vector()
{

clear();

delete[] _begin;

_begin = _end = _endofstorage = nullptr;
}

拷贝构造函数(深拷贝)

现代写法:

vector( const vector<T> & s )
{

        reserve(s.capacity());//提前开好空间

        for( auto& e : s )//使用引用,防止拷贝构造,提升效率
        {

        push_bakc(e);//注意数据要进行深拷贝
        }
}

迭代器

由于物理空间上连续,与指针的行为相似

typedef T* iterator ;

typedef const T* const_iterator;

要注意*this是const成员还是非const成员

iterator begin()
{
        return _begin;
}

iterator end()
{
return _end;

}

const_iterator begin()const
{
       return (const T*) _begin;
}

const_iterator end() const
{

return (const T*)_end;

}

const T& operator[](int npos) const 
{

assert( npos < size() );//注意未初始化的地方不能使用
return _begin[npos];

}

 T& operator[](int npos) 
{

assert( npos < size() );
return _begin[npos];

}

运算符重载

vector<T>& operator=(  vector<T>  s) (构造 加 交换 )
{
       swap(s,*this);

       return *this;
}

insert函数

主要是在某个位置之前插入一个值或一段区间

样列:

#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(5);
    s.insert(s.begin() + 1, 10);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

样列:

#include<string>
#include<vector>
#include<iostream>
using namespace std;
int main()
{
    
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(5);
    string k("asdfasfsaf");
    s.insert(s.begin() + 1, k.begin() + 2 , k.end() - 4);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
}

erase函数(一般不会缩容)

删除某个位置的值 , 或删除一段区间的值(左闭右开)

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    vector<int> s;
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.push_back(1);
    s.erase(s.begin(), s.end() - 1);
    for (auto& e : s)
    {
        cout << e << " ";
    }
    cout << endl;
    return 0;
}

注意在使用insert函数和erase函数会造成迭代器失效,所以在使用完迭代器之后,就不能在使用,

如果你就要使用,则要更新迭代器

举个例子:(删除顺序表中的偶数)

#include<iostream>
#include<vector>
using namespace std;
int main()
{
    vector<int> s;
    s.push_back(1);
    s.push_back(2);
    s.push_back(3);
    s.push_back(4);
    s.push_back(4);
    s.push_back(9);
    s.push_back(11);
    s.push_back(11);
    s.push_back(11);
    auto it = s.begin();
    while (it != s.end())
    {
        if (*it % 2 == 0)it = s.erase(it);
        else it++;
    }
    for (auto& e : s)cout << e << " ";
    cout << endl;
    return 0;
}

push_back 和 pop_back

尾增 和 尾删

reserve和resize函数

reserve函数时扩容,reserve使用完,不能用[]赋值

resize函数是扩容(当newcapacity > newcapacity) + 初始化

要注意reserve函数在完成扩容时,是对数据进行深拷贝(不能使用memcpy)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/640001.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Kafak详解(1)

简介 消息队列 为什么要有消息队列 图-1 消息队列的使用 消息队列 1)消息Message&#xff1a;网络中的两台计算机或者两个通讯设备之间传递的数据。例如说&#xff1a;文本、音乐、视频等内容。 2)队列Queue&#xff1a;一种特殊的线性表(数据元素首尾相接)&#xff0c;特…

echarts折线图默认不显示数据圆点,鼠标划上之后折线图才显示圆点

只需要设置showSymbol为false就可以了&#xff0c;表示只在 tooltip hover 的时候显示。 代码如下&#xff1a; option {tooltip: {trigger: axis},xAxis: {type: category,data: [Mon, Tue, Wed, Thu, Fri, Sat, Sun]},yAxis: {type: value},series: [{data: [150, 230, 224…

什么是防抖和节流?有什么区别? 如何实现?

防抖&#xff08;Debounce&#xff09;和节流&#xff08;Throttle&#xff09;是两种常用的技术手段&#xff0c;主要用于控制某个函数在一定时间内触发的次数&#xff0c;以减少触发频率&#xff0c;提高性能并避免资源浪费。 防抖&#xff08;Debounce&#xff09;的工作原…

图像哈希:GLCM+DCT

文章信息 作者&#xff1a;Ziqing Huang期刊&#xff1a;IEEE&#xff08;一区&#xff09;题目&#xff1a;Perceptual Image Hashing with Texture and Invariant Vector Distance for Copy Detection 目的、实验步骤及结论 目的&#xff1a;使用GLCM进行全局特征的提取&am…

Python 数据库简化操作:dataset 库介绍

文章目录 Python 数据库简化操作&#xff1a;dataset 库介绍第一部分&#xff1a;背景介绍第二部分&#xff1a;库是什么&#xff1f;第三部分&#xff1a;如何安装这个库&#xff1f;第四部分&#xff1a;库函数使用方法第五部分&#xff1a;场景应用第六部分&#xff1a;常见…

C++初阶学习第二弹——C++入门(下)

C入门&#xff08;上&#xff09;&#xff1a;C初阶学习第一弹——C入门&#xff08;上&#xff09;-CSDN博客 目录 一、引用 1.1 引用的实质 1.2 引用的用法 二、函数重载 三、内敛函数 四、auto关键字 五、总结 前言&#xff1a; 在上面一章我们已经讲解了C的一些基本…

echarts 双堆叠柱状图(数据整理)

1.后台返回的数据格式 {"code": "0000","message": "","messageCode": "操作成功","sign": null,"detail": null,"data": {"pieChart": [{"key": "产品…

Git下载安装

天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物。 每个人都有惰性&#xff0c;但不断学习是好好生活的根本&#xff0c;共勉&#xff01; 文章均为学习整理笔记&#xff0c;分享记录为主&#xff0c;如有错误请指正&#xff0c;共同学习进步。…

就业班 第三阶段(负载均衡) 2401--4.19 day3 nginx3

二、企业 keepalived 高可用项目实战 1、Keepalived VRRP 介绍 keepalived是什么keepalived是集群管理中保证集群高可用的一个服务软件&#xff0c;用来防止单点故障。 ​ keepalived工作原理keepalived是以VRRP协议为实现基础的&#xff0c;VRRP全称Virtual Router Redundan…

RAG部署 | 使用TensorRT-LLM在Windows上部署检索增强生成聊天机器人RAG

项目应用场景 面向 Windows 平台部署 RAG 检索增强生成聊天机器人场景&#xff0c;项目采用 TensorRT-LLM 进行 GPU 加速推理&#xff0c;注意项目需要 RT4090 及以上的英伟达显卡支持。 项目效果 项目细节 > 具体参见项目 README.md (1) 下载构建好的 Llama2 TensorRT 模型…

[RTOS 学习记录] 复杂工程项目的管理

[RTOS 学习记录] 复杂工程项目的管理 这篇文章是我阅读《嵌入式实时操作系统μCOS-II原理及应用》后的读书笔记&#xff0c;记录目的是为了个人后续回顾复习使用。 前置内容&#xff1a; 工程管理工具make及makefile 文章目录 1 批处理文件与makefile的综合使用1.1 批处理文件…

BootstrapAdmin Net7:基于RBAC的后台管理框架,实现精细化权限管理与多站点单点登录

BootstrapAdmin Net7&#xff1a;基于RBAC的后台管理框架,实现精细化权限管理与多站点单点登录 摘要 随着企业信息化建设的不断深入&#xff0c;后台管理系统在企业运营中扮演着越来越重要的角色。本文介绍了一款基于RBAC&#xff08;Role-Based Access Control&#xff09;的…