Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >向量类模板的声明和实现---扩充版本

向量类模板的声明和实现---扩充版本

作者头像
大忽悠爱学习
发布于 2021-11-15 02:39:26
发布于 2021-11-15 02:39:26
56300
代码可运行
举报
文章被收录于专栏:c++与qt学习c++与qt学习
运行总次数:0
代码可运行

Vector.hpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#pragma once
#include<cstdlib>
#define SPACE_MAX 16  //表示数组的最小长度
template<class T>
class Vector
{
private:
	T* data;//维护动态数组的指针
	int size;//数组的数据元素的个数
	int max;//当前数组最大能容纳的元素个数
	void Error(const char* cs)const { cout << cs << endl; exit(1); }//错误信息报告
public:
	//这里的构造函数,里面的形参n,决定了当前数组的长度,但为了防止长度不够用,减少扩容次数,这里会给n+ SPACE_MAX作为数组最大容纳元素个数
	explicit Vector(int n = 0) :size(0), max(n + SPACE_MAX),data(NULL)
	{
		if (max > 0)
			data = new T[max];
	};
	//复制构造函数
	Vector(const Vector& v):data(NULL),max(0)
	{
		//这里用深拷贝---防止堆区内存重复释放
		data = new T[v.max];
		size = v.size;
		max = v.max;
		for (int i = 0; i < size; i++)
		{
			data[i] = v.data[i];
		}
	}
	//析构函数
	~Vector()
	{
		delete[] data;
	}
	//赋值运算符重载
	Vector& operator=(const Vector<T>& v);
	//下标运算符重载
	T& operator[](int id)
	{
		return data[id];
	}
	//常量型下标运算符重载---只有后置const可以作为重载条件,前置不行
	const T& operator[](int id)const
	{   
		return data[id];
	}
	//判断是否为空
	bool Empty()const
	{
		return size == 0;
	}
	//求当前容器中元素个数
	int Size()const
	{
		return size;
	}
	//求数组最大的容量
	int Max()const
	{
		return max;
	}
	//清空数组
	void Clear()const
	{
		size = 0;
	}
	//迭代器
	typedef T* iterator;
	//const型迭代器
	typedef const T* const_iterator;
	//返回开始迭代器
	iterator Begin()
	{
		return data;
	}
	const_iterator Begin()const
	{
		return data;
	}
	//返回结束迭代器
	iterator End()
	{
		return data+size;
	}
	const_iterator End()const
	{
		return data + size;
	}
	//返回首元素的引用
	const T& Front()const
	{
		return data[0];
	}
	T& Front()
	{
		return data[0];
	}
	//返回尾元素的引用
	const T& Back()const
	{
		return data[size - 1];
	}
     T& Back()
	{
		return data[size - 1];
	}
	 //尾插
	 void Push_back(const T& item)
	 {
		 data[size++] = item;
	 }
	 //尾删
	 void Pop_back()
	 {
		 size--;
	 }
	 //扩容函数
	 void Reserve(int newMax);
	 //增值函数
	 void resize(int newSize, const T& item);
	 //插入函数--插入到指定迭代器之前,返回的迭代器指向新元素所处位置
	 iterator Insert(iterator itr, const T& item);
	 //删除函数----删除迭代器指向位置的数据,返回迭代器,但此时迭代器指向的值应该是未删除前位置的后一个位置元素
	 iterator Erase(iterator itr);
};
//赋值运算符重载
template<class T>
Vector<T>& Vector<T>::operator=(const Vector<T>& v)
{
	//先判断两个容器最大值是否相等
	if (max != v.max)
	{
		//深拷贝防止堆区内存重复释放
		delete[] data;
		max = v.max;
		data = new T[max];
	}
	size = v.size;
	for (int i = 0; i < size; i++)
		data[i] = v[i];
	return *this;
}
//扩容函数
template<class T>
void Vector<T>::Reserve(int newMax)
{
	//如果当前newMax比max还小,拿扩了个寂寞,当然直接返回喽!
	if (newMax < max) return;
	//进行扩容操作--开辟新空间存放原来的数据
	//我们要先保留原数组
	T* old = data;
	data = new T[newMax];
	for (int i = 0; i < size; i++)
		data[i] = old[i];
	//除了新的数组最大容量需要更新,别的不需要
	max = newMax;
	delete[] old;
}
//增值函数
template<class T>
void Vector<T>::resize(int newSize, const T& item)
{
	//如果新增元素个数比最大容量都多,要干嘛?----扩容啊,愣着干嘛呢!
	if (newSize > max)
		Reserve(newSize * 2 + 1);
	//把新增加的元素初始化为item
	for (int i = size; i < newSize; i++)
		data[i] = item;
	size = newSize;
}
//插入函数--插入到指定迭代器之前,返回的迭代器指向新元素所处位置
//这里注意typename---因为
template<class T>
typename Vector<T>::iterator Vector<T>::Insert(iterator itr, const T& item)
{
	//容量已满,要先扩容
	if (size == max)
	{
		Reserve(size * 2 + 1);
	}
	//把要插入位置之后的元素统统后移一位,从数组最后一个元素开始一个个往后移
	for (iterator p = data + size, q = data + size - 1; p != itr; --p, --q)
	{
		//p迭代器在q迭代器之后
		//注意原itr位置的元素也要往后移,这就是为什么结束条件是p!=itr
		*p = *q;
	}
	*itr = *item;
	size++;
	return itr;
}
//删除函数----删除迭代器指向位置的数据,返回迭代器,但此时迭代器指向的值应该是未删除前位置的后一个位置元素
template<class T>
typename Vector<T>::iterator Vector<T>::Erase(iterator itr)
{
	//从删除位置开始的后一个元素依次前移一位,直到数组最后一个元素移动后,结束
	for (iterator p = itr, q = itr + 1; q != data + size; ++p, ++q)
	{
		*p = *q;
	}
	size--;
	return itr;
}

main.cpp

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<iostream>
using namespace std;
#include"Vector.hpp"
template<class iterator>
void display(iterator first,iterator last)
{
	for (; first != last; ++first)
	{
		cout << *first << " ";
	}
	cout << endl;
}
void test()
{
	Vector<int> v;
	for (int i = 0; i < 10; i++)
		v.Push_back(i);
	//这里类型已经确定了,就不用在通过typename来声明类型
	Vector<int>::iterator itr = v.Begin();
	cout << "after operator++: " << endl;
	cout << *(++itr) << endl;
	cout << "after operator--" << endl;
	cout << *(--itr) << endl;
	v.Erase(itr);
	cout << "after eraseing the first: " << endl;
	display(v.Begin(), v.End());
	v.Pop_back();
	cout << "after erasing the last: " << endl;
	cout << v.Front() << endl;
	cout << v.Back() << endl;

	Vector<int> v1 = v;
	v1.Reserve(20);
	v1.resize(20, 5);
	cout << "v1.size= " << v1.Size() << endl;
	for (int i = 0; i < v1.Size(); ++i)
		v1[i]++;
	cout << "after reserve(20),resizing(20,5) and adding(1): " << endl;
	display(v1.Begin(), v1.End());
	cout << "v1.size= " << v1.Size() << endl;
}
int main()
{
	test();
	return 0;
}

补充:删除[first,last)区间的数据,返回当前数据的位置的erase重载函数。

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T > typename Vector<T>::iterator Vector<T>::Erase(iterator first, iterator last)
{
	//计算删除的元素个数
	int num = last - first;
     //删除指定区间里面的元素
	if (last != End())
	{
		//计算剩余需要移动的元素个数
		int leftNum = End() - last;
		iterator p = first, q = last;
		for (int i = 0; i < leftNum; i++,++p,++q)
		{
			*p = *q;
		}
	}
	size -= num;
	//返回first迭代器之前的一个元素
	return first;
}

推荐下面一种写法:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
template<class T > typename Vector<T>::iterator Vector<T>::Erase(iterator first, iterator last)
{
	iterator p = first;
	iterator q = last;
	for (; q != data + size; ++p, ++q)
		*p = *q;
	size -= last - first;
	return first;
}

补充:在pos处插入另一个Vector容器指定区间[first, last)的数据的函数

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//在pos处插入另一个Vector容器指定区间[first, last)的数据
template<class T> void Vector<T>::Insert(iterator pos, iterator first, iterator last)
{
	//计算需要插入的元素个数
	int num = last - first;
	if (num + size > max)
		Reserve((num + size) * 2);
	//先把从pos位置开始的元素后移num个位置
	for (iterator p = End(), q = End() + num; p != pos - 1; --p, --q)
		*q = *p;
	//从pos位置开始,依次插入num个新元素
	for (int i = 0; i < num; i++)
		*pos++ = *first++;
	size += num;
}

补充: 交换两个Vector中的数据—swap函数

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//交换两个Vector中的数据
template<class T>
void Vector<T>::Swap(Vector<T>& v)
{
	//交换指针的指向
	T* temp = data;
	data = v.data;
	v.data = temp;
	//交换元素个数
	int t = size;
	size = v.size;
	v.size = t;
	//交换数组容量
	int m = max;
	max = v.max;
	v.max = m;
}

推荐写法—该写法需注意深拷贝问题:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//交换两个Vector中的数据
template<class T>
void Vector<T>::Swap(Vector<T>& v)
{
	Vector<T> temp = *this;
	*this = v;
	v=temp;
}

注意:

  • 其实在C++Primer书上的P593页下半部分,有解释的,C++语言默认情况下,假定通过作用域运算符访问的名字不是类型,所以当我们要访问的是类型时候,必须显示的告诉编译器这是一个类型,通过关键字typename来实现这一点
  • 类模板继承时,如果无法直接使用父类函数和变量,需要加作用域

typename用法大佬的文章详细讲解

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2021/04/27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
你真的知道如何正确清除 DNS 缓存吗?( 附全平台详细教程 )
DNS 缓存是一个临时数据库,用于存储有关以前的 DNS 查找的信息。换句话说,每当你访问网站时,你的操作系统和网络浏览器都会保留该域和相应 IP 地址的记录。这消除了对远程 DNS 服务器重复查询的需要,并允许你的 OS 或浏览器快速解析网站的 URL。
iMike
2019/10/21
47.2K0
你真的知道如何正确清除 DNS 缓存吗?( 附全平台详细教程 )
工具推荐|时间久了,电脑上网网速慢了,一招教你解决
使用电脑上网时间久了,电网上网刷新网页的速度明显慢了不少,是什么问题呢,下面让我一步步教你如何让自己的电脑健步如飞,快速冲浪。
六月暴雪飞梨花
2024/04/25
2400
工具推荐|时间久了,电脑上网网速慢了,一招教你解决
如何在 Linux 上刷新 DNS 缓存?
DNS(域名系统)是互联网的一项服务,它作为将域名和 IP 地址相互映射的一个分布式数据库,能够使人更方便地访问互联网,而不用记住能够被机器直接读取的 IP 数串。在使用域名访问网站时,电脑会将域名解析为 IP 地址。为了提高解析速度,操作系统通常会将解析过的地址存储在 DNS 缓存中。
网络技术联盟站
2024/06/13
1.6K0
如何在 Linux 上刷新 DNS 缓存?
DNS or hosts ?
作为一名IT攻(dǎ)城(gōng)狮(rén),肯定会听过、看过或者在你最初的面试中遇到过这个经典的问题:
仙人技术
2021/08/31
6.5K0
DNS or hosts ?
清除Dns缓存_怎么清除ip地址缓存
dnsmasq的是一个轻量级的DNS、TFTP和DHCP服务器。它的目的是给局域网提供配对的DNS和DHCP服务。 dnsmasq接受DNS查询,并从一个小的本地高速缓存应答它们或将其转发到一个真正的递归DNS服务器。该软件也被安装在很多便宜的路由器上来缓存DNS查询。只需重新启动dnsmasq的服务来清除DNS缓存:
全栈程序员站长
2022/09/20
7.3K0
【详解】ping得通外网IP,ping不通外网域名的解决办法
在日常的网络管理或开发过程中,有时会遇到一个奇怪的问题:能够通过IP地址成功ping通外网服务器,但使用域名时却无法ping通。这种情况下,问题通常不在于网络连接本身,而可能是DNS解析出现了问题。本文将探讨几种可能的原因及相应的解决方法。
大盘鸡拌面
2025/01/26
8400
如何不违法访问github
(ps:如果你不想看中间的知识点讲解,我将我配置好的网络节点放在第三步,欢迎大家自取!)
猫咪-9527
2025/01/13
4260
如何不违法访问github
iStore软路由自定义DNS服务
作者:matrix 被围观: 9 次 发布时间:2024-06-10 分类:零零星星 | 无评论 »
HHTjim 部落格
2024/06/11
2.6K0
iStore软路由自定义DNS服务
Mac 强制刷新本地的 DNS 缓存
一般情况下,修改了域名的 DNS 解析,在本地访问该域名时,解析到的 IP 值还是旧的,想立即解析到最新值,那么就需要清理本地的 DNS 缓存,在终端中执行如下命令即可:
轻量级云原生架构实验室
2022/11/30
10.4K2
如何在 Linux 上刷新 DNS 缓存?
DNS(Domain Name System)是一个用于将域名解析为相应 IP 地址的网络服务。在 Linux 操作系统上,为了提高 DNS 查询的性能和效率,系统会缓存最近的 DNS 查询结果。但有时候你可能需要手动刷新 DNS 缓存,以便获取最新的 DNS 解析结果。本文将介绍如何在 Linux 上刷新 DNS 缓存,并提供详细的步骤。
网络技术联盟站
2023/06/19
8.7K0
如何在 Linux 上刷新 DNS 缓存?
使用系统hosts文件进行域名解析
hosts文件用于将域名(主机名)映射到IP地址。它在所有操作系统(包括Linux,Windows和macOS)都是一个纯文本文件。hosts文件允许你设置指定映射域名的IP地址。这个更改只作用于当前计算机,而不会影响全域网的解析方式。 hosts文件优先于DNS。当你键入要访问的网站的域名时,必须将域名转换为其对应的IP地址。操作系统首先检查其hosts文件中是否存在相应的域名,如果该域名没有条目,它将查询配置的DNS服务器以解析指定的域名。 如果你想在不更改域DNS设置的情况下测试你的网站,这将非常有用
入门笔记
2022/06/02
5.5K0
如何解决 Error 1001 DNS解析错误:Error 1001 DNS Resolution Error`(Ray ID: 917c89...)从诊断到修复的完整指南
当您访问网站时遭遇 Error 1001 DNS Resolution Error(Ray ID: 917c89…)时,意味着用户的请求在到达目标服务器之前,DNS解析环节已经失败。本文将从技术原理到实践操作,系统性地解析该错误的解决方案。
猫头虎
2025/02/27
3650
如何解决 Error 1001 DNS解析错误:Error 1001 DNS Resolution Error`(Ray ID: 917c89...)从诊断到修复的完整指南
笔记 | SwitchHosts自动刷新DNS缓存和重启nscd服务[Ubuntu]
众所周知,Github在国内由于DNS污染而常常无法访问。故而诞生了种种解决手段。其中修改本地hosts文件直接进行本地DNS解析是其中一个合法且免费的手段。
Ranlychan
2023/03/05
3.5K0
笔记 | SwitchHosts自动刷新DNS缓存和重启nscd服务[Ubuntu]
DNS 解析问题:DNS 解析失败,无法访问域名
是山河呀
2025/02/05
2.6K0
GitHub访问不了或者很慢的解决办法
国内网络访问 Github 速度过慢的原因有许多,但其中最直接和原因是其 CND 域名遭到 DNS 污染,导致我们无法连接使用 GitHub 的加速服务,因此访问速度缓慢。简单理解:CDN「Content Delivery Network」,即内容分发网络,依靠部署在各地的边缘服务器,平衡中心服务器的负荷,就近提供用户所需内容,提高响应速度和命中率。DNS 污染,是指一些刻意或无意制造出来的数据包,把域名指向不正确的 IP 地址,阻碍了网络访问。我们默认从目标网址的最近 CDN 节点获取内容,但当节点过远或 DNS 指向错误时,就会操成访问速度过慢或无法访问的问题。
天乐404
2023/11/16
12.6K0
GitHub访问不了或者很慢的解决办法
Linux缓存服务NSCD用法总结及实践 - Name Service Cache Daemon
NSCD (Name Service Cache Daemon)是一个系统缓存服务,用于缓存常见的名称服务信息,例如用户、组、主机名和服务。它可以提高系统的性能,减少对名称服务的频繁查询和网络流量,从而加快系统的响应速度。
RokasYang
2023/03/20
10.9K0
Linux缓存服务NSCD用法总结及实践 - Name Service Cache Daemon
Google hosts - 简单介绍与使用方法
可以自己百度Google hosts寻找最新的hosts文件,获取前往GitHub上由大佬们维护的项目获取:https://github.com/googlehosts/hosts
雨临Lewis
2022/01/11
27.4K0
告别无法访问的github(附解决方案)
本来很多域名对应的IP地址都是由上游可信赖的服务器提供的,这样可以降低网络上的流量压力
行哥玩Python
2021/11/23
21.1K0
解决github图片及网页加载不出来
兮动人
2023/09/03
5650
DNSmasq的使用(一)
DNSmasq是一个用于配置DNS和DHCP的轻便工具,适合小型网络,利用得当可以防污染,防劫持,消除广告,还可以搭配其他软件实现更多功能
Huramkin
2018/09/17
3.4K0
相关推荐
你真的知道如何正确清除 DNS 缓存吗?( 附全平台详细教程 )
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验