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

C++初阶——简单实现vector

目录

1、前言

2、Vector.h

3、Test.cpp


1、前言

简单实现std::vector类模板。

相较于前面的string,vector要注意

深拷贝,因为vector的元素可能是类类型,类类型元素可以通过赋值重载自己实现深拷贝

迭代器失效,其实无非是两种(现在认为):

1. 迭代器更新了,但是认为用的是之前的迭代器,可以先保存值。

2. 迭代器没有更新,但是认为是用更新后的迭代器,那就更新迭代器。

2、Vector.h

#pragma once#include <iostream>
#include <vector>
#include <assert.h>using namespace std;namespace Lzc
{template <class T>class vector{public:typedef T* iterator;typedef const T* const_iterator;vector() // 有了拷贝构造,就不会生成默认构造,但是需要默认构造{}vector(size_t n, const T& val = T())// int有默认构造int(),为了兼容模板{reserve(n);for (size_t i = 0; i < n; i++){push_back(val);}}template <class InputIterator> // 使用别的容器的迭代器初始化vector(InputIterator first, InputIterator last){// reserve(last - first);// last - first 有迭代器不支持减while (first != last){push_back(*first);++first;}}vector(const vector<T>& v){reserve(v.size());for (int i = 0; i < v.size(); i++){push_back(v[i]);}}void swap(vector<T>& tmp){std::swap(_start, tmp._start);std::swap(_finish, tmp._finish);std::swap(_end_of_storage, tmp._end_of_storage);}vector<T>& operator=(const vector<T>& v){vector tmp(v);swap(tmp);return *this;}~vector(){if (_start){delete[] _start;_start = _finish = _end_of_storage = nullptr;}}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;}void clear(){_finish = _start;}bool empty() 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 resize(size_t n, const T& val = T()); // resize一般用于扩容+初始化void reserve(size_t n);void push_back(const T& val){if (size() == capacity())reserve(capacity() == 0 ? 4 : 2 * capacity());*_finish = val;++_finish;}void pop_back(){assert(size() > 0);--_finish;}iterator insert(iterator pos, const T& val);iterator erase(iterator pos);private:iterator _start = nullptr;iterator _finish = nullptr;iterator _end_of_storage = nullptr;};template<class T>void vector<T>::resize(size_t n, const T& val) // resize一般用于扩容+初始化{if (n < size()){_finish = _start + n;}else{reserve(n);while (_finish < _start + n){*_finish = val;++_finish;}}}template<class T>void vector<T>::reserve(size_t n){if (n > capacity()){size_t old_size = size();T* tmp = new T[n];for (size_t i = 0; i < old_size; i++){tmp[i] = _start[i]; // 若为类类型,会赋值重载,先释放,再深拷贝}delete[] _start;_start = tmp;_finish = tmp + old_size; // 不能调用size(),因为_start已更新,所以先保存size()_end_of_storage = tmp + n;}}// vector<T>::iterator编译器认为是类中的静态变量,typename告诉编译器是类型template<class T>typename vector<T>::iterator vector<T>::insert(iterator pos, const T& val){assert(pos <= _finish);assert(pos >= _start);if (size() == capacity()){size_t old_pos = pos - _start; // 扩容后pos没有指向新空间reserve(capacity() == 0 ? 4 : 2 * capacity());pos = _start + old_pos;}iterator it = _finish;while (it != pos){*it = *(it - 1); // 若为类类型,会赋值重载,先释放,再深拷贝--it;}*pos = val;++_finish;return pos;}template<class T>typename vector<T>::iterator vector<T>::erase(iterator pos){assert(pos >= _start);assert(pos < _finish);iterator it = pos + 1;while (it != end()){*(it - 1) = *it; // 若为类类型,会赋值重载,先释放,再深拷贝++it;}--_finish;return pos;}template<class Container> // 什么容器都能打印void print_Container(const Container& v){for (const auto& e : v){cout << e << " ";}cout << endl;}
}

3、Test.cpp

#include "Vector.h"
#include <list>
#include <string>namespace Lzc
{void test_vector1(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);for (size_t i = 0; i < v.size(); i++){cout << v[i] << " ";}cout << endl;//vector<int>::iterator it = v.begin();auto it = v.begin();while (it != v.end()){cout << *it << " ";++it;}cout << endl;for (auto e : v){cout << e << " ";}cout << endl;vector<double> vd;vd.push_back(1.1);vd.push_back(1.2);vd.push_back(1.3);vd.push_back(1.4);vd.push_back(1.5);print_Container(vd);}void test_vector2(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);v.push_back(5);print_Container(v);// 若iterator insert(iterator& pos, const T& val)// 下面的临时变量(具有常性),不能传引用/*v.insert(v.begin() + 2, 30);print_vector(v);*/int x;cin >> x;auto p = find(v.begin(), v.end(), x);if (p != v.end()){// insert以后p就是失效,不要直接访问,要访问就要更新这个失效的迭代器的值/*v.insert(p, 20);(*p) *= 10;*/p = v.insert(p, 40);(*(p + 1)) *= 10;}print_Container(v);}void test_vector3(){vector<int> v;v.push_back(1);v.push_back(2);v.push_back(3);v.push_back(4);//v.push_back(5);print_Container(v);// 删除所有的偶数auto it = v.begin();while (it != v.end()){if (*it % 2 == 0){it = v.erase(it); // 删除了,相当于++了}else{++it;}}print_Container(v);}void test_vector4(){int i = int(); // int有默认构造int(),为了兼容模板int j = int(1);int k(2);vector<int> v;v.resize(10, 1);v.reserve(20);print_Container(v);cout << v.size() << endl;cout << v.capacity() << endl;v.resize(15, 2);print_Container(v);v.resize(25, 3);print_Container(v);v.resize(5);print_Container(v);}void test_vector5(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);print_Container(v1);vector<int> v2 = v1;print_Container(v2);vector<int> v3;v3.push_back(10);v3.push_back(20);v3.push_back(30);v1 = v3;print_Container(v1);print_Container(v3);}void test_vector6(){vector<int> v1;v1.push_back(1);v1.push_back(2);v1.push_back(3);v1.push_back(4);v1.push_back(4);v1.push_back(4);vector<int> v2(v1.begin(), v1.begin() + 3);print_Container(v1);print_Container(v2); // 1 2 3list<int> lt;lt.push_back(10);lt.push_back(10);lt.push_back(10);lt.push_back(10);vector<int> v3(lt.begin(), lt.end()); print_Container(lt);print_Container(v3);// 10 10 10 10vector<string> v4(10, "1111111");print_Container(v4);vector<int> v5(10);print_Container(v5);vector<int> v6(10u, 1); // 指定构造函数,不然编译器会使用模板函数。print_Container(v6);    // vector(size_t n, const T& val = T())//vector<int> v7(10, 1); // 编译器会使用模板函数,报错//print_Container(v7); // 可以再重载一个vector(int n, const T& val = T())}void test_vector7() // 扩容后需深拷贝{vector<string> v;v.push_back("11111111111111111111");v.push_back("11111111111111111111");v.push_back("11111111111111111111");v.push_back("11111111111111111111");print_Container(v);v.push_back("11111111111111111111");print_Container(v);}
}int main()
{Lzc::test_vector7();return 0;
}

相关文章:

C++初阶——简单实现vector

目录 1、前言 2、Vector.h 3、Test.cpp 1、前言 简单实现std::vector类模板。 相较于前面的string&#xff0c;vector要注意&#xff1a; 深拷贝&#xff0c;因为vector的元素可能是类类型&#xff0c;类类型元素可以通过赋值重载&#xff0c;自己实现深拷贝。 迭代器失效…...

1.21作业

1 unserialize3 当序列化字符串中属性个数大于实际属性个数时&#xff0c;不会执行反序列化 外部如果是unserialize&#xff08;&#xff09;会调用wakeup&#xff08;&#xff09;方法&#xff0c;输出“bad request”——构造url绕过wakeup 类型&#xff1a;public class&…...

深度集成DeepSeek大模型:WebSocket流式聊天实现

目录 5分钟快速接入DeepSeek大模型&#xff1a;WebSocket实时聊天指南创建应用开发后端代码 (Python/Node.js)结语 5分钟快速接入DeepSeek大模型&#xff1a;WebSocket实时聊天指南 创建应用 访问DeepSeek官网 前往 DeepSeek官网。如果还没有账号&#xff0c;需要先注册一个。…...

Jmeter连接数据库、逻辑控制器、定时器

Jmeter直连数据库 直接数据库的使用场景 直连数据库的关键配置 添加MYSQL驱动Jar包 方式一&#xff1a;在测试计划面板点击“浏览”按钮&#xff0c;将你的JDBC驱动添加进来 方式二&#xff1a;将MySQL驱动jar包放入到lib/ext目录下&#xff0c;重启JMeter 配置数据库连接信…...

『Linux笔记』进程间通信(IPC)详细介绍!

进程间通信&#xff08;IPC&#xff09;详细介绍&#xff01; 文章目录 一. 进程间通信&#xff08;IPC&#xff09;详细介绍1. 共享内存&#xff08;Shared Memory&#xff09;2. 消息队列&#xff08;Message Queues&#xff09;3. 信号量&#xff08;Semaphores&#xff09…...

Jmeter进阶篇(34)如何解决jmeter.save.saveservice.timestamp_format=ms报错?

问题描述 今天使用Jmeter完成压测执行,然后使用命令将jtl文件转换成html报告时,遇到了报错! 大致就是说jmeter里定义了一个jmeter.save.saveservice.timestamp_format=ms的时间格式,但是jtl文件中的时间格式不是标准的这个ms格式,导致无法正常解析。对于这个问题,有如下…...

Visual Studio 2022配置网址参考

代码格式化和清理冗余代码选项的配置&#xff1a; 代码样式选项和代码清理 - Visual Studio (Windows) | Microsoft Learn 调试时传递参数&#xff1a; 调试时传递命令行参数&#xff08;C&#xff09; - Visual Studio (Windows) | Microsoft Learn...

Redis中集合(Set)常见命令详解

集合&#xff08;Set&#xff09;常见命令详解 集合&#xff08;Set&#xff09;在Redis中是一种无序且不可重复的数据结构&#xff0c;非常适合用于存储唯一元素的集合。以下是Redis集合操作的一些常用命令及其详细说明&#xff1a; 添加成员 sadd key member [member ...]…...

动态规划

简介 动态规划最核心两步&#xff1a; 状态表示&#xff1a;dp[i]代表什么状态转移方程&#xff1a;如何利用已有的dp求解dp[i] 只要这两步搞对了&#xff0c; 就完成了动态规划的%95 剩下的就是细节问题&#xff1a; dp初始化顺序&#xff08;有时是倒序&#xff09;处理边…...

stm32rtc实时时钟详解文章

目录 stm32 后备区域基础知识详解 stm32 bkp基础知识详解 Unix时间戳基础知识详解 stm32 rtc实时时钟基础知识详解 相关代码初始化配置 欢迎指正&#xff0c;希望对你&#xff0c;有所帮助&#xff01;&#xff01;&#xff01; stm32 后备区域基础知识详解 stm32芯片的 …...

DeepSeek 助力 Vue 开发:打造丝滑的 键盘快捷键(Keyboard Shortcuts)

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 Deep…...

【第一节】C++设计模式(创建型模式)-工厂模式

目录 前言 一、面向对象的两类对象创建问题 二、解决问题 三、工厂模式代码示例 四、工厂模式的核心功能 五、工厂模式的应用场景 六、工厂模式的实现与结构 七、工厂模式的优缺点 八、工厂模式的扩展与优化 九、总结 前言 在面向对象系统设计中&#xff0c;开发者常…...

深入理解 SQL 注入漏洞及解决方案

一、引言 在当今数字化时代&#xff0c;数据库作为存储和管理数据的核心组件&#xff0c;其安全性至关重要。SQL 注入是一种常见且极具威胁性的数据库安全漏洞&#xff0c;它可能导致数据泄露、篡改甚至系统被完全控制。本文将深入探讨 SQL 注入漏洞的产生原因、表现形式以及如…...

使用 deepseek实现 go语言,读取文本文件的功能,要求支持 ascii,utf-8 等多种格式自适应

使用 deepseek实现 go语言&#xff0c;读取文本文件的功能&#xff0c;要求支持 ascii&#xff0c;utf-8 等多种格式自适应我要用 chatgpt&#xff0c;也问过&#xff0c;但是比 deepseek 还是差一个级别&#xff0c;具体如下&#xff1a; package mainimport ("bufio&qu…...

7.【线性代数】——求解Ax=0,主列和自由列

七 求解Ax0&#xff0c;主列和自由列 1. 消元、秩、特解特解零空间 2. 简化行阶梯形式 :主元上下都是0&#xff0c;主元简化为1 1. 消元、秩、特解 矩阵消元 [ 1 2 2 2 2 4 6 8 3 6 8 10 ] ⏟ A ⇒ r o w 2 − 2 r o w 1 , r o w 3 − 3 r o w 1 [ 1 2 2 2 0 0 2 4 0 0 2 4 ]…...

vue3结合后端传递过来的文件进行预览功能

业务的需要&#xff0c;前端需要根据后端传递过来的文件流进行预览的功能&#xff0c;前端点击链接直接触发浏览器的窗口的预览功能。 实现方式一&#xff1a; 使用弹窗和iframe的标签的形式进行预览文件&#xff0c;但是iframe可能会出现网站安全性的问题&#xff0c;限制比较…...

【Python爬虫(39)】掌控全局:分布式爬虫的任务管理与监控之道

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

Jenkins整合Jmeter实现接口自动化测试

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 一、安装jmeter 下载&#xff1a;http://jmeter.apache.org/download_jmeter.cgi 这里我用了一台Windows安装jmeter用来写接口测试的脚本&#xff0c;启动前修改j…...

Web 自动化测试提速利器:Aqua 的 Web Inspector (检查器)使用详解

Web 自动化测试提速利器:Aqua 的 Web Inspector (检查器)使用详解 前言简介一、安装二、Web Inspector 的使用2.1 获取元素定位器(Locators)2.2 将定位器添加到代码2.3 验证定位器2.4 处理 Frames (框架)总结前言 JetBrains 的 Aqua IDE 提供强大的 Web Inspector 工具,帮…...

大语言模型:从开发到运行的深度解构

一、LLM开发训练的全流程解析 1. 数据工程的炼金术 数据采集&#xff1a;构建涵盖网页文本&#xff08;Common Crawl&#xff09;、书籍、论文、代码等领域的超大规模语料库&#xff0c;典型规模可达数十TB。例如GPT-4的训练数据包含超过13万亿token数据清洗&#xff1a;通过…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

第19节 Node.js Express 框架

Express 是一个为Node.js设计的web开发框架&#xff0c;它基于nodejs平台。 Express 简介 Express是一个简洁而灵活的node.js Web应用框架, 提供了一系列强大特性帮助你创建各种Web应用&#xff0c;和丰富的HTTP工具。 使用Express可以快速地搭建一个完整功能的网站。 Expre…...

【根据当天日期输出明天的日期(需对闰年做判定)。】2022-5-15

缘由根据当天日期输出明天的日期(需对闰年做判定)。日期类型结构体如下&#xff1a; struct data{ int year; int month; int day;};-编程语言-CSDN问答 struct mdata{ int year; int month; int day; }mdata; int 天数(int year, int month) {switch (month){case 1: case 3:…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

【Linux】C语言执行shell指令

在C语言中执行Shell指令 在C语言中&#xff0c;有几种方法可以执行Shell指令&#xff1a; 1. 使用system()函数 这是最简单的方法&#xff0c;包含在stdlib.h头文件中&#xff1a; #include <stdlib.h>int main() {system("ls -l"); // 执行ls -l命令retu…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...

linux 下常用变更-8

1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行&#xff0c;YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID&#xff1a; YW3…...

【从零学习JVM|第三篇】类的生命周期(高频面试题)

前言&#xff1a; 在Java编程中&#xff0c;类的生命周期是指类从被加载到内存中开始&#xff0c;到被卸载出内存为止的整个过程。了解类的生命周期对于理解Java程序的运行机制以及性能优化非常重要。本文会深入探寻类的生命周期&#xff0c;让读者对此有深刻印象。 目录 ​…...