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.mzph.cn/news/827208.shtml

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

相关文章

第二部分-Foundation基础-学习导航

专题地址&#xff1a;MacOS一站式程序开发系列专题 第一部分&#xff1a;基础入门-学习导航 ObjectiveC-第一部分-基础入门-学习导航 第二部分&#xff1a;Foundation基础学习导航 Foundation框架-13-数据对象&#xff1a;主要讲述NSRange, NSString, NSValue, NSNull, NSD…

模型量化技术

量化(Quantization)技术专注于用较少的信息表示数据&#xff0c;同时尽量不损失太多准确性。 具体来说&#xff0c;量化会将模型参数使用的数据类型&#xff0c;转换为更少位数表示&#xff0c;并尽可能达到相同信息的效果。 例如&#xff0c;假设您的模型权重原始以32位(32-b…

CFCASSL证书的网络安全解决方案

在数字化时代&#xff0c;网络信息安全的重要性不言而喻。随着电子商务、在线交易、远程办公等互联网活动的日益普及&#xff0c;确保数据传输的安全性与隐私保护成为企业和用户共同关注的焦点。在此背景下&#xff0c;CFCA SSL证书作为一种权威、高效的网络安全解决方案&#…

[LitCTF 2023]PHP是世界上最好的语言!!、 [LitCTF 2023]Vim yyds、 [羊城杯 2020]easycon

目录 [LitCTF 2023]PHP是世界上最好的语言&#xff01;&#xff01; [LitCTF 2023]Vim yyds [羊城杯 2020]easycon [LitCTF 2023]PHP是世界上最好的语言&#xff01;&#xff01; 无参&#xff0c;根据题目提示看看php能否执行——返回1执行成功 用system()函数调用、执行ls …

C++教你如何模拟实现string,如何实现string写时拷贝

文章目录 前言成员变量默认成员函数默认构造函数拷贝构造函数析构函数赋值运算符重载 容量相关函数&#xff08;Capacity&#xff09;reserve函数resize函数size函数capacity 函数clear函数 修改函数&#xff08;Modifiers&#xff09;swap函数insert函数字符插入字符串插入 ap…

LRU缓存(哈希+双链表)

题目描述 请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;…

基于docker搭建瀚高数据库HighGo6.0.1【图文】

基于docker搭建瀚高数据库HighGo6.0.1 拉取镜像启动验证进入容器 登录数据库查看数据库加密方式修改加密方式为sm3进入数据库修改密码重启容器 数据库验证数据库密码到期参考 docker部署 https://blog.csdn.net/weixin_44385419/article/details/127738868 拉取镜像 docker p…

【Java】变量零基础教程

目录 一、引言 二、基本组成单位 三、变量的基本原理 四、变量的基本使用步骤 五、变量快速入门 六、变量使用的注意事项 一、引言 为什么需要变量&#xff1f; ​​​​​​一个程序就是一个世界。 大家看下图&#xff0c;是我们现实中的一张生活照&#xff0c;图里有树…

spring aop介绍

Spring AOP&#xff08;面向切面编程&#xff09;是一种编程范式&#xff0c;它允许开发者将横切关注点&#xff08;cross-cutting concerns&#xff09;从业务逻辑中分离出来&#xff0c;从而提高代码的模块化。在传统的对象导向编程中&#xff0c;这些横切关注点&#xff0c;…

Yarn 安装与配置:简化 JavaScript 项目依赖管理

在现代 JavaScript 项目开发中&#xff0c;管理依赖项是一项关键任务。Yarn 作为 Facebook、Google、Exponent 和 Tilde 联合推出的 JavaScript 包管理工具&#xff0c;以其快速、可靠和安全的特性&#xff0c;赢得了开发者的广泛青睐。本文将引导您在主流操作系统上安装 Yarn&…

ic基础|时序篇:握手协议valid和ready的时序优化

大家好&#xff0c;我是数字小熊饼干&#xff0c;一个练习时长两年半的ic打工人。我在两年前通过自学跨行社招加入了IC行业。现在我打算将这两年的工作经验和当初面试时最常问的一些问题进行总结&#xff0c;并通过汇总成文章的形式进行输出&#xff0c;相信无论你是在职的还是…

Maven的常用基本命令

Maven是一个Java项目的构建和依赖管理工具&#xff0c;它有一系列命令用于项目的构建、清理、安装、部署等操作。以下是一些Maven的常用命令及其详细解释与举例&#xff1a; 1.mvn clean 功能&#xff1a;清理项目构建过程中生成的中间文件和目标目录&#xff08;target&…

【华为OD机试】分月饼【C卷|200分】

【华为OD机试】-真题 !!点这里!! 【华为OD机试】真题考点分类 !!点这里 !! 题目描述 中秋节,公司分月饼,m 个员工,买了 n 个月饼,m ≤ n,每个员工至少分 1 个月饼,但可以分多个,单人分到最多月饼的个数是 Max1 ,单人分到第二多月饼个数是 Max2 ,Max1 - Max2 ≤ 3 ,…

HarmonyOS开发案例:【视频播放器】

介绍 基于video、swiper和slider组件&#xff0c;实现简单的视频播放器&#xff0c;可支持海报轮播、视频播放等功能。 相关概念 [video组件]&#xff1a;视频播放组件。[swiper组件]&#xff1a;滑动容器&#xff0c;提供切换子组件显示的能力。[slider组件]&#xff1a;滑…

秋招之路 面经

这里参考一位很厉害的前辈所分享的他的嵌入式软件工程师秋招之路&#xff0c;自己详细的读了一下他的经历以及他的分享的秋招面试和项目经验的总结。 我的嵌入式软件工程师秋招之路&#xff08;文末送福利&#xff09;_嵌入式软件工程师 刷leetcode-CSDN博客 如何在面试中介绍…

针对窗口数量多导致窗口大小显示受限制的问题,使用滚动条控制窗口

建议&#xff1a;首先观察结果展示&#xff0c;判断是否可以满足你的需求。 目录 1. 问题分析 2. 解决方案 2.1 界面设计 2.2 生成代码 2.3 源码实现 3. 结果展示 1. 问题分析 项目需要显示的窗口数量颇多&#xff0c;主界面中&#xff0c;如果一次性显示全部窗口&#x…

Web3钱包开发获取测试币-Base Sepolia(二)

Web3钱包开发获取测试币-Base Sepolia(二) ![在这里插入图片描述](https://img-blog.csdnimg.cn/direct/b0c0ac86b04a496087471388532bc54a.png) 基于上篇 Web3钱包开发获取测试币-Polygon Mumbai(一) &#xff1a;https://suwu150.blog.csdn.net/article/details/137949473 我…

MyBatis 框架学习(I)

MyBatis 框架学习(I) 文章目录 MyBatis 框架学习(I)1. 介绍2. 准备&测试3. MyBatis 注解基础操作3.1 日志输出3.2 Insert 操作3.3 Delete 操作3.4 Update 操作3.5 Select 操作 总结 1. 介绍 之前我们学习过利用JDBC操作数据库进行项目开发&#xff0c;但我们发现它操作起来…

设计模式学习笔记 - 开源实战二(中):从Unix开源开发学习应对大型复杂项目开发

概述 项目越复杂、代码量越多、参与开发人员越多、开发维护时间越长&#xff0c;我们就要越重视代码质量。代码质量下降会导致项目研发困难重重&#xff0c;比如&#xff1a;开发效率低&#xff0c;找了很多人&#xff0c;天天加班也出活不多&#xff1b;线上 bug 频发&#x…

LINUX固定USB设备名称

在Linux系统中&#xff0c;USB串口设备的名称通常是根据设备连接的顺序动态分配的。因此&#xff0c;当设备重新连接时&#xff0c;它可能会被分配不同的设备文件名&#xff08;如/dev/ttyUSB0、/dev/ttyUSB1等&#xff09;。要固定USB串口设备的名称&#xff0c;你可以使用ude…