2.2 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
非模板语法与模板语法差异对比图


代码与注释如下
#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++数据结构与算法(全部答案)
相关文章:

2.2 Vector<T> 动态数组(模板语法)
C数据结构与算法 目录 本文前驱课程 1 C自学精简教程 目录(必读) 2 动态数组 Vector(难度1) 其中,2 是 1 中的一个作业。2 中详细讲解了动态数组实现的基本原理。 本文目标 1 学会写基本的C类模板语法; 2 为以后熟练使用 S…...

dockerfile 例子(二)
Dockerfile由一行一行的命令语句组成,#开头的为注释行。Dockerfile文件内容分为四个部分:基础镜像信息、维护者信息、镜像操作指令以及容器启动执行指令。 接下来给大家列出Dockerfile中主要命令的说明。 FROM,指定所创建镜像的基础镜像。 …...

openssh---Windows下git安装配置gitlab
安装openssh 1. 专业版Win10/11默认自带,可以查看是否开启 1. Get-WindowsCapability -Online | Where-Object Name -like OpenSSH* 2. Add-WindowsCapability -Online -Name OpenSSH.Client~~~~0.0.1.0 3. Add-WindowsCapability -Online -Name OpenSSH.Serve…...

vscode宏键绑定
开发语言php 实现输入[ 得到 [];的效果 [win]ctrlp,[mac]superp 输入>keyboard 选择 在json文件里增加(目前有缺陷,sublime的设置是比较完美的.或者phpstorm默认不需要配置): {"key": "[","command": "editor.action.insertSnippet&…...

外贸企业如何借助CRM提升企业发展?
外贸企业竞争激烈,提高自身竞争力,扩大海外业务市场,是每个外贸企业的目标。为了实现这一目标,不少外贸企业借助CRM系统,优化业务流程,管理维护客户,从而实现可持续发展。那么,外贸企…...

初步了解ES
一、ES基础查询 1、es基础查询 1.1 准备数据 # 准备数据 PUT test_index/_doc/1 {"name":"顾老二","age":30,"from": "gu","desc": "皮肤黑、武器长、性格直","tags": ["黑", &…...
Linux基础(三)
一.系统基本优化 关闭selinux:getenforce 查看selinux状态setenforce 0 临时关闭vim /etc/sysconfig/selinux 永久关闭SELINUXdisabled 关闭防火墙:systemctl stop firewalld 临时关闭防火墙systemctl disable firewalld 永久关闭防火墙sys…...
python函数调用的四种方式
第一种:参数按顺序从第一个参数往后排#标准调用 def normal_invoke(x, y):print("--normal_invoke:--" )print("x is %d" %x )print("y is %d" %y) # 标准调用 normal_invoke(1, 2) 运行结果: --normal_invoke:-- x is 1 …...

如何将两个pdf合并成一个?pdf合并技巧分享
在日常工作过程当中,我们经常需要处理一些文件,而文件的处理往往是琐碎的,想要提高工作效率,需要选择一些合适的方法,并掌握一定的技巧,那么,如何将两个pdf合并成一个?pdf合并技巧有哪些呢?接…...
qt : day 3
1.完成登录框的按钮操作,并在登录成功后进行界面跳转 ------------------------------------------------------------------ .pro ------------------------------------------------------------------ QT core gui texttospeech greaterThan(QT_MAJOR_V…...

flutter高德地图大头针
1、效果图 2、pub get #地图定位 amap_flutter_map: ^3.0.0 amap_flutter_location: ^3.0.0 3、上代码 import dart:async; import dart:io;import package:amap_flutter_location/amap_flutter_location.dart; import package:amap_flutter_location/amap_location_option…...

【线性代数】矩阵求导的本质与分子布局、分母布局的本质(矩阵求导——本质篇)
矩阵求导的本质与分子布局、分母布局的本质(矩阵求导——本质篇) 说在前面一. 函数与标量、向量、矩阵二. 矩阵求导的本质三. 矩阵求导结果的布局四. 分子布局、分母布局的本质五. 向量变元的实值标量函数 说在前面 我将严谨地说明矩阵求导的本质与分子布…...

快速了解状态管理库Pinia及其使用方法
目录 1.pinia是什么 2.为什么要使用pinia 3.pinia的优点 4.pinia在项目中使用 ①创建一个使用pinia的Vue3项目 ②在页面使用store 1.pinia是什么 Pinia 起源于一次探索 Vuex 下一个迭代的实验,如果你学过Vue2,那么你一定使用过Vuex。Vuex在Vue2中主…...

scratch绘制同心圆 2023年5月中国电子学会图形化编程 少儿编程 scratch编程等级考试四级真题和答案解析
目录 scratch绘制同心圆 一、题目要求 1、准备工作 2、功能实现 二、案例分析 <...

【LeetCode】3. 无重复字符的最长子串
3. 无重复字符的最长子串(中等) 方法:滑动窗口 哈希表 思路 这道题主要用到思路是:滑动窗口 什么是滑动窗口? 其实就是一个队列,比如例题中的 abcabcbb,进入这个队列(窗口)为 ab…...

苹果macOS 14开发者预览版Beta 7发布 新增超过100款视频壁纸和屏保
8 月 31 日,苹果向 Mac 电脑用户推送了 macOS 14 开发者预览版 Beta 7 更新(内部版本号:23A5337a),本次更新距离上次发布隔了 8 天。 苹果发布 Beta 7 更新的同时,还发布了第 6 个公测版,正式版…...

Redis 7 第五讲 事务、管道、发布订阅 过渡篇
事务 理论 可以一次执行多个命令,本质是一组命令的集合。一个事务中的所有命令都会序列化,按顺序地串行化执行而不会被其它命令插入,不许加塞 一个队列中,一次性、顺序性、排他性的执行一系列命令 Redis事务 VS 关系型数据库事务…...

[SpringBoot3]视图技术Thymeleaf
七、视图技术Thymeleaf Thymeleaf是一个表现层的模板引擎,一般被使用在Web环境中,它可以处理HTML、XML、JS等文档,简单来说,它可以将JSP作为Java Web应用的表现层,有能力展示与处理数据。这样,同一个模板文…...

wangluobiancheng
UDP send: receive: TCP...

大数据之hadoop入门
大数据概念 大数据:无法在一定时间范围内用常规软件工具进行捕捉、管理和处理的数据集合,是需要新处理模式才能具有更强的决策力、洞察发现李和流程优化能力的海量、高增长率和多样化的信息资产。 大的概念是相对来说的:目前来说࿰…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...

以下是对华为 HarmonyOS NETX 5属性动画(ArkTS)文档的结构化整理,通过层级标题、表格和代码块提升可读性:
一、属性动画概述NETX 作用:实现组件通用属性的渐变过渡效果,提升用户体验。支持属性:width、height、backgroundColor、opacity、scale、rotate、translate等。注意事项: 布局类属性(如宽高)变化时&#…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

CMake基础:构建流程详解
目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Nuxt.js 中的路由配置详解
Nuxt.js 通过其内置的路由系统简化了应用的路由配置,使得开发者可以轻松地管理页面导航和 URL 结构。路由配置主要涉及页面组件的组织、动态路由的设置以及路由元信息的配置。 自动路由生成 Nuxt.js 会根据 pages 目录下的文件结构自动生成路由配置。每个文件都会对…...

微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...

HashMap中的put方法执行流程(流程图)
1 put操作整体流程 HashMap 的 put 操作是其最核心的功能之一。在 JDK 1.8 及以后版本中,其主要逻辑封装在 putVal 这个内部方法中。整个过程大致如下: 初始判断与哈希计算: 首先,putVal 方法会检查当前的 table(也就…...

push [特殊字符] present
push 🆚 present 前言present和dismiss特点代码演示 push和pop特点代码演示 前言 在 iOS 开发中,push 和 present 是两种不同的视图控制器切换方式,它们有着显著的区别。 present和dismiss 特点 在当前控制器上方新建视图层级需要手动调用…...

【网络安全】开源系统getshell漏洞挖掘
审计过程: 在入口文件admin/index.php中: 用户可以通过m,c,a等参数控制加载的文件和方法,在app/system/entrance.php中存在重点代码: 当M_TYPE system并且M_MODULE include时,会设置常量PATH_OWN_FILE为PATH_APP.M_T…...