Vector<T> 动态数组(模板语法)

C++数据结构与算法 目录

本文前驱课程

1 C++自学精简教程 目录(必读)

2 动态数组 Vector(难度1)

其中,2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。

本文目标

1 学会写基本的C++类模板语法;

2 为以后熟练使用 STL 打下基础;

3 为更进一步的阅读和掌握更多的C++库打下基础;

模板语法的学习最恰当的方式就是和非模板代码对比学习。

本文的内容只是在 2 动态数组 Vector(难度1)的基础上,把代码改造为模板语法。

除此之外,不添加任何内容。

模板语法介绍

当类的成员变量是不确定的类型的时候,我们使用模板类( template class)来实现这样的类。

模板类的定义如下:

    template<typename T>  struct Vector{T data;//成员变量 data 的类型不确定,写成 T};

解释说明:

(1)template 表示后续代码中有类型是不确定的,先用typename T当中的T表示类型;

(2)typename表示T是一个未来才能确定的类型

(3)确定T的类型的方式就是创建一个Vector对象的时候在<>中指定:

 Vector<int> arr;  //这条语句表示用int替换代码中的T

非模板语法与模板语法差异对比图

模板语法和非模板语法对比1

模板语法和非模板语法对比2

代码与注释如下

#include<iostream>
#include <iomanip>
#include <cassert>
using namespace std;//------下面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------
#include <algorithm>
#include <cstdlib>
#include <iostream> 
#include <vector>
#include <utility>
using namespace std;
struct Record { Record(void* ptr1, size_t count1, const char* location1, int line1, bool is) :ptr(ptr1), count(count1), line(line1), is_array(is) { int i = 0; while ((location[i] = location1[i]) && i < 100) { ++i; } }void* ptr; size_t count; char location[100] = { 0 }; int line; bool is_array = false; bool not_use_right_delete = false; }; bool operator==(const Record& lhs, const Record& rhs) { return lhs.ptr == rhs.ptr; }std::vector<Record> myAllocStatistic; void* newFunctionImpl(std::size_t sz, char const* file, int line, bool is) { void* ptr = std::malloc(sz); myAllocStatistic.push_back({ ptr,sz, file, line , is }); return ptr; }void* operator new(std::size_t sz, char const* file, int line) { return newFunctionImpl(sz, file, line, false); }void* operator new [](std::size_t sz, char const* file, int line)
{ return newFunctionImpl(sz, file, line, true); }void operator delete(void* ptr) noexcept { Record item{ ptr, 0, "", 0, false }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); } }void operator delete[](void* ptr) noexcept {Record item{ ptr, 0, "", 0, true }; auto itr = std::find(myAllocStatistic.begin(), myAllocStatistic.end(), item); if (itr != myAllocStatistic.end()) { auto ind = std::distance(myAllocStatistic.begin(), itr); myAllocStatistic[ind].ptr = nullptr; if (!itr->is_array) { myAllocStatistic[ind].not_use_right_delete = true; } else { myAllocStatistic[ind].count = 0; }std::free(ptr); }}
#define new new(__FILE__, __LINE__)
struct MyStruct { void ReportMemoryLeak() { std::cout << "Memory leak report: " << std::endl; bool leak = false; for (auto& i : myAllocStatistic) { if (i.count != 0) { leak = true; std::cout << "leak count " << i.count << " Byte" << ", file " << i.location << ", line " << i.line; if (i.not_use_right_delete) { cout << ", not use right delete. "; }	cout << std::endl; } }if (!leak) { cout << "No memory leak." << endl; } }~MyStruct() { ReportMemoryLeak(); } }; static MyStruct my; void check_do(bool b, int line = __LINE__) { if (b) { cout << "line:" << line << " Pass" << endl; } else { cout << "line:" << line << " Ohh! not passed!!!!!!!!!!!!!!!!!!!!!!!!!!!" << " " << endl; exit(0); } }
#define check(msg)  check_do(msg, __LINE__);
//------上面的代码是用来测试你的代码有没有问题的辅助代码,你无需关注------//注意:禁止修改Vector的定义,包括禁止给Vector添加成员变量;
//可以添加私有成员函数,如果你认为需要的话template<typename T>
struct Vector
{
public:Vector();Vector(int n, T value);Vector(const Vector& from);Vector(int* begin, int* end);~Vector();int size() const;//只读元素//参考 https://zhuanlan.zhihu.com/p/539451614const T& operator[](int n)const { return m_data[n]; }//写入元素T& operator[](int n) { return m_data[n]; }void push_back(T value);bool empty() const;// your job 1void clear();// your job 2Vector& operator = (const Vector& from);// your job 4
private:void copy(const Vector& from);// your job 3
private:int m_element_cout;int m_capacity;T* m_data;//定义一个元素类型待定的数组起始元素的指针//请忽略下面这个成员变量,这个成员变量不影响你的实现,当它不存在即可。
};//模板类的成员函数都要以下面的template语法开始,和类声明的地方一样
template<typename T>
Vector<T>::Vector()
{m_element_cout = 0;m_capacity = 10;m_data = new int[m_capacity];
}template<typename T>
Vector<T>::Vector(int n, T value) :Vector()
{for (int i = 0; i < n; i++)push_back(value);
}template<typename T>
Vector<T>::Vector(const Vector& from)
{m_element_cout = from.m_element_cout;m_capacity = from.m_capacity;m_data = new int[m_capacity];for (int i = 0; i < m_element_cout; i++){m_data[i] = from.m_data[i];}
}template<typename T>
Vector<T>::Vector(int* begin, int* end) :Vector()
{for (int* p = begin; p < end; p++){push_back(*p);}
}template<typename T>
Vector<T>::~Vector()
{delete[] m_data;
}template<typename T>
int Vector<T>::size() const
{return m_element_cout;
}template<typename T>
void Vector<T>::push_back(T value)
{if (m_element_cout < m_capacity){m_data[m_element_cout] = value;m_element_cout++;}else{int* p;p = new T[2 * m_capacity];for (int j = 0; j < m_element_cout; j++){p[j] = m_data[j];}p[m_element_cout] = value;m_element_cout = m_element_cout + 1;m_capacity = 2 * m_capacity;delete[]m_data;m_data = p;}
}//(1) your code for : Vector empty()//(2) your code for : Vector clear()//(3) your code for : Vector copy()//(4) your code for : Vector operator =void test1(void)
{Vector<int> v;//创建一个存放int变量的容器vint i;check(v.size() == 0);for (i = 0; i < 10; i++){v.push_back(i);}for (int i = 0; i < 10; i++){check(v[i] == i);}check(v.size() == 10);
}
void test2(void)
{int n = 100000;Vector<int> v;int i;check(v.size() == 0);for (i = 0; i < n; i++){v.push_back(i);}for (int i = 0; i < n; i++){assert(v[i] == i);}check(v.size() == n);
}
void print(Vector<int>& v, const std::string& msg)
{std::cout << "The contents of " << msg.c_str() << " are:";for (int i = 0; i != v.size(); ++i){std::cout << ' ' << v[i];}std::cout << '\n';
}
void test3()
{Vector<int> a;Vector<int> first;                   // empty vector of intscheck(first.empty() == true && first.size() == 0);Vector<int> second(4, 100);                       // four ints with value 100check(second.empty() == false);check(second.size() == 4);Vector<int> fourth(second);                       // a copy of thirdcheck(fourth.size() == second.size());int myints[] = { 16,2,77,29 };Vector<int> fifth(myints, myints + sizeof(myints) / sizeof(int));check(fifth.empty() == false);check(fifth[0] == 16);check(fifth[3] == 29);check(fifth.size() == sizeof(myints) / sizeof(int));print(fifth, "fifth");//The contents of fifth are:16 2 77 29 fifth.push_back(30);check(fifth[4] == 30);check(fifth.size() == 5);print(fifth, "fifth");//The contents of fifth are:16 2 77 29 30 check(fifth.size() == sizeof(myints) / sizeof(int) + 1);first = fifth = fifth;print(first, "first");//The contents of first are:16 2 77 29 30 check(first.empty() == false && first.size() == fifth.size());Vector<int> a1(myints, myints + sizeof(myints) / sizeof(int));//下面大括号是作用域,用来把代码分开互不干扰,这样就可以创建相同的变量名字了,就不用为了起很多不同的变量名而烦恼了。{Vector<int> b(a1);b.push_back(2);check(b[4] == 2);}{Vector<int> c;c = a1;}check(a1.size() == sizeof(myints) / sizeof(int));{Vector<int> c;c = fifth;c[0] = 1;check(c[0] == 1);}
}int main()
{test1();test2();test3();return 0;
}

预期输出:

答案在此

C++数据结构与算法(全部答案)

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

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

相关文章

基于Java的代驾管理系统 springboot+vue,mysql数据库,前台用户、商户+后台管理员,有一万五千字报告,完美运行

基于Java的代驾管理系统 springbootvue&#xff0c;mysql数据库&#xff0c;前台用户、商户后台管理员&#xff0c;有一万五千字报告&#xff0c;完美运行。 系统完美实现用户下单叫车、商户接单、管理员管理系统&#xff0c;页面良好&#xff0c;系统流畅。 各角色功能&#x…

【CicadaPlayer】getPlayerBufferDuration分析

https://github.com/alibaba/CicadaPlayer/blob/release/0.4.4/mediaPlayer/SuperMediaPlayer.cpp核心关键函数int64_t SuperMediaPlayer::getPlayerBufferDuration(bool gotMax, bool internal)17个地方出现: getPlayerBufferDuration的durations 数组 分别 对音频、视频、字…

利用R作圆环条形图

从理念上看&#xff0c;本质就是增加了圆环弧度的条形图。如上图2。 需要以下步骤&#xff1a; 数据处理&#xff0c;将EXCEL中的数据做成3*N的表格导入系统&#xff0c;代码如下&#xff1a;library(tidyverse) library(stringr)library(ggplot2)library(viridis) stuper &…

UDP 多播(组播)

前言&#xff08;了解分类的IP地址&#xff09; 1.组播&#xff08;多播&#xff09; 单播地址标识单个IP接口&#xff0c;广播地址标识某个子网的所有IP接口&#xff0c;多播地址标识一组IP接口。单播和广播是寻址方案的两个极端&#xff08;要么单个要么全部&#xff09;&am…

AI聊天机器人平台Poe发布更新;自然语言理解课程概要

&#x1f989; AI新闻 &#x1f680; AI聊天机器人平台Poe发布更新 突破功能限制 增加企业级服务 摘要&#xff1a;知名问答网站Quora旗下的AI聊天机器人平台Poe发布了一系列更新&#xff0c;包括推出Mac应用、支持同时进行多个对话、接入Meta的Llama 2模型等功能。用户只需支…

自动化运维:Ansible之playbook基于ROLES部署LNMP平台

目录 一、理论 1.playbook剧本 2.ROLES角色 3.关系 4.Roles模块搭建LNMP架构 二、实验 1.Roles模块搭建LNMP架构 三、问题 1.剧本启动php报错语法问题 2.剧本启动mysql报错语法问题 3.剧本启动nginx开启失败 4.剧本安装php失败 5.使用yum时报错 6.rpm -Uvh https…

自动泊车的自动驾驶控制算法

1. 自动泊车系统 自动泊车系统(AutomatedParkingASSiSt,APA)利用车辆搭载的传感器感知车辆周边环境,扫描满足当前车辆停放的障碍物空间车位或线车位,并通过人机交互(HumanMachine Interface,HMI)获取驾驶员对目标车位的选择或自动确定目标车位,自动规划泊车路径,通过控制器向车…

windows环境搭建ELK

目录 资源下载&#xff08;8.9.1&#xff09; ES安装、注册、使用 Kibana安装、注册、使用 Logstash安装、注册、使用 Filebeat安装、使用&#xff08;如果只有一个数据流&#xff0c;则不需要使用filebeat&#xff0c;直接上logstash即可&#xff09; 资源下载&#xff0…

WebSocket--技术文档--架构体系--《WebSocket实现原理以及关键组件》

WebSocket产生背景 简单的说&#xff0c;WebSocket协议之前&#xff0c;双工通信是通过多个http链接来实现&#xff0c;这导致了效率低下。WebSocket解决了这个问题。下面是标准RFC6455中的产生背景概述。 长久以来, 创建实现客户端和用户端之间双工通讯的web app都会造成HTT…

配置开启Hive远程连接

配置开启Hive远程连接 Hive远程连接默认方式远程连接Hive自定义身份验证类远程连接Hive权限问题额外说明 Hive远程连接 要配置Hive远程连接&#xff0c;首先确保HiveServer2已启动并监听指定的端口 hive/bin/hiveserver2检查 HiveServer2是否正在运行 # lsof -i:10000 COMMA…

详解 ElasticSearch Kibana 配置部署

默认安装部署所在机器允许外网 SSH工具 Putty 链接&#xff1a;https://pan.baidu.com/s/1b6gumtsjL_L64rEsOdhd4A 提取码&#xff1a;lxs9 Winscp 链接&#xff1a;https://pan.baidu.com/s/1tD8_2knvv0EJ5OYvXP6VTg 提取码&#xff1a;lxs9 WinSCP安装直接下一步到完成…

elementUi中的el-table表格的内容根据后端返回的数据用不同的颜色展示

效果图如下&#xff1a; 首先 首先&#xff1a;需要在表格行加入 <template slot-scope"{ row }"> </template>标签 <el-table-column prop"usable" align"center" label"状态" width"180" ><templ…

ELK安装、部署、调试 (二) ES的安装部署

ElasticSearch是一个基于Lucene的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎&#xff0c;基于RESTful web接口操作ES&#xff0c;也可以利用Java API。Elasticsearch是用Java开发的&#xff0c;并作为Apache许可条款下的开放源码发布&#xff0c;是当前流行的企业…

Linux 桌面上的 Firefox 面临着大问题

导读毫无疑问&#xff0c;无论是在桌面、笔记本电脑还是移动设备上&#xff0c;浏览器都是任何操作系统中最重要的应用之一。 如果没有一个功能强大、快速且稳定的浏览器&#xff0c;操作系统的实用性将大幅度降低&#xff0c;以至于我相当确定&#xff0c;如果一个操作系统没有…

Mysql的page,索引,Explain Type等基本常识

Mysql的基本问题 Mysql 为什么建议使用自增id&#xff1f; 因为id&#xff08;主键&#xff09;是自增的话&#xff0c;那么在有序的保存用户数据到页中的时候&#xff0c;可以天然的保存&#xff0c;并且是在聚集索引&#xff08;id&#xff09;中的叶子节点可以很好的减少插…

WebGL非矩阵变换

目录 平移 示例代码&#xff1a; 齐次坐标矢量的最后一个分量w 旋转 p的坐标&#xff0c;可得等式 R1&#xff1a; 使用r、α、β来表示点p的坐标&#xff0c;可得等式 R2&#xff1a; 利用三角函数两角和公式&#xff0c;可得等式 R3&#xff1a; 最后&#xff0c;将…

下岗吧,Excel

ChatGPT的诞生使Excel公式变得过时。通过使用 ChatGPT 的代码解释器你可以做到&#xff1a; 分析数据创建图表 这就像用自然语言与电子表格交谈一样。我将向大家展示如何使用 ChatGPT 执行此操作并将结果导出为Excel格式&#xff1a; 作为示例&#xff0c;我将分析并创建美国…

阿里云效和阿里在线idea使用

阿里云效 https://flow.aliyun.com/all?page1 阿里在线idea&#xff1a;https://ide.aliyun.com/ 在云效中创建的项目可以在在线idea 打开 运行中的项目 设置ssh 设置以后可以使用云效率的代码构建来构建代码 设置 添加自有云或者体验5h

元素居中的方法总结

目录 垂直居中 行内元素垂直居中 单行文本垂直居中 1.line-height: 200px; 多行文本垂直居中 1.tablevertical-align:middle 块级元素垂直居中 1.display: flex;align-items: center; 2.使用position top margin-top 水平居中 行内元素水平居中 1.text-align:cente…

如何让你的jupyter notebook 排版得像Word(Markdown和网页文件写法)

案例背景 很多时候我们在jupyter notebook里面的写代码&#xff0c;画图&#xff0c;但是文字分析什么的写在里面纯文本不好看&#xff0c;需要进行排版&#xff0c;那么就得用markdown的写法&#xff0c;如何还想居中或者更花里胡哨的字体&#xff0c;那就得要网页文件的一些…