02c++模板部分讲解

1理解函数模板

#include<iostream>
using namespace std;//函数模板
template<typename T> //定义一个模板参数列表
//模板类型参数 typename/class
bool compare(T a, T b)
{cout << "template compare: " << endl;return a > b;
}template<>
bool compare(const char* a, const char* b)
{cout << "compare(char*)";return strcmp(a, b) > 0;
}//非模板函数
bool compare(const char* a, const char* b)
{cout << "normal compare: " << endl;return strcmp(a, b) > 0;
}
/*函数调用点,编译器用用户指定的类型,从原来的模板实例化一份函数代码出来*/
int main()
{compare<int>(10, 20);compare(20, 30); //推导出来是整形 模板实参法推演//compare(30, 4.5);b报错,找不到compare<int>(30, 3.4); //这样子可以但是被会警告//对于某些类型来说,依赖编译器默认实例化的模板代码,代码处理逻辑是有错误的compare("aaa", "bbb"); //不能a>b来处理//模板的特例化,不是编译器提供的,而是用户提供的实例化return 0;
}
//份文件的时候 直接告诉编译器模板指定类型的模板实例化
template bool compare<int>(int, int);
template bool compare<double>(double, double);

2、理解类模板

#include<iostream>
using namespace std;template<typename T, const int SIZE>
void sort(T* arr)
{for (int i = 0; i < SIZE - 1; i++){for (int j = 0; j < SIZE - 1 - i; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}
//类模板
int main()
{int arr[] = { 12,2,2,2,2,2 };const int size = sizeof(arr) / sizeof(arr[0]);sort<int, size>(arr);for (int val : arr){cout << val << " ";}cout << endl;
}#include<iostream>
using namespace std;
#include<time.h>
template<typename T> //模板+参数列表 = 类名称
class SeqStack
{
public://构造函数和析构函数不要加模板类型参数列表SeqStack(int size = 10):_stack(new T[size]),_top(0),_size(size){}~SeqStack(){delete[]_stack;_stack = nullptr;}SeqStack<T>(const SeqStack<T>& stack):_top(stack._top),_size(stack._size){_stack = new T[_size];//不要用memcopy进行拷贝for (int i = 0; i < _top; i++){_stack[i] = stack._stack[i];}}SeqStack<T>& operator = (const SeqStack<T>& stack){if (this == &stack)return *this;delete[] _stack;_top = stack._top;_size = stack._size;_stack = new T[_size];//不要用memcopy进行拷贝for (int i = 0; i < _top; i++){_stack[i] = stack._stack[i];}return *this;}void push(const T& val){if (full())expand();_stack[_top++] = val;}void pop(){if (empty()){return;}--_top;}T top() const{if ((empty()))throw "stack is empty()"; //抛出异常结束return _stack[_top - 1];}bool full()const{return _top == _size;}bool empty()const{return _top == 0;}
private:T* _stack;int _top;int _size;//顺序栈底层数void expand(){T* ptmp = new T[_size * 2];for (int i = 0; i < _top; i++){ptmp[i] = _stack[i];}delete[]_stack;_stack = ptmp;ptmp = nullptr;_size *= 2;}
};
int main()
{SeqStack<int>stack(4);for (int i = 0; i < 20; i++){stack.push(rand() % 100);}while (!stack.empty()){cout << stack.top() << " ";stack.pop();}cout << endl;SeqStack<int>stack1(2);stack1.push(1);stack1.push(2);stack1.push(3);stack1.push(4);stack1.pop();cout << stack1.top();return 0;
}

3、SLT实现Vector类

#include<iostream>
using namespace std;template<class T>
class Vector
{
public:Vector(int size = 10){_first = new T[size];_last = _first;_end = _first + size;}~Vector(){delete[]_first;_first = _last = _end = nullptr;}Vector(const Vector<T>& rhs){int size = rhs._end - rhs._first;_first = new T[size]; //空间大小int len = rhs._last - rhs._first;for (int i = 0; i < len; i++){_first[i] = rhs._first[i];}_last = _first + len;_end = _first + size;}Vector<T>& operator=(const Vector<T>& rhs) //拷贝构造{if (this == &rhs)return *this;delete[] _first;int size = rhs._end - rhs._first;int len = rhs._last - rhs._first;for (int i = 0; i < len; i++){_first[i] = rhs._first[i];}_last = _first + len;_end = _first + size;return *this;}void push_back(const T& val){if (full()){expand();}*_last = val;_last++;}void pop_back(){if (empty()){return;}--_last;}T back()const //返回容器末尾的元素值{return *(_last - 1);}bool full()const { return _last == _end; }bool empty()const { return _first == _last; }int size()const { return _last - _first; }private:void expand(){int _size = _end - _first;T* tmp = new T[_size * 2];for (int i = 0; i < _size; i++){tmp[i] = _first[i];}delete[]_first;_first = tmp;_last = _first + _size;_size *= 2;_end = _first + _size;}T* _first; //指向数组的起始的位置T* _last; //指向数组有效元素的后继位置T* _end; //指向数组空间的后继位置};
//容器空间分配器
class Test
{
public:Test() { cout << "test()" << endl; }~Test() { cout << "~test()" << endl; }
};int main()
{/*Vector<int>vec;for (int i = 0; i < 20; i++){vec.push_back(rand() % 100);}while (!vec.empty()){cout << vec.back() << " ";vec.pop_back();}cout << endl;vec.push_back(10);cout << vec.back() << endl;cout << endl;*/Vector<Test>vec;return 0;
}

6、容器空间配置

#include<iostream>
using namespace std;/*
template <class _Ty,class _Alloc = allocator<_Ty>>class Vector容器的空间配置器allocator做四件事情 内存开辟 内存释放 对象构造 对象析构
*///定义容器的空间配置器,和c++标准库的allocator实现一样
template<typename T>
class Allocator
{
public:T* allocate(size_t size) //负责内存开辟{return (T*)malloc(sizeof(T) * size);}void deallocate(void* p) //负责内存释放{free(p);}void construct(T* p, const T& val) //负责对象构造{new (p) T(val);//定位new}void destroy(T* p)//负责对象析构{p->~T();//代表了T类型的析构函数}
};
template<typename T, typename Alloc = Allocator<T>>
class Vector
{
public:Vector(int size = 10){//需要把内存开辟和对象构造分开处理//_first = new T[size];_first = _allocator.allocate(size);_last = _first;_end = _first + size;}~Vector(){//delete[]_first;//析构有效的元素,然后释放_first指针指向的堆内存for (T* p = _first; p != _last; p++){_allocator.destroy(p); //把first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first);//释放堆上的数组内存_first = _last = _end = nullptr;}Vector(const Vector<T>& rhs){int size = rhs._end - rhs._first;//_first = new T[size]; //空间大小_first = _allocator.allocate(size);int len = rhs._last - rhs._first;for (int i = 0; i < len; i++){//_first[i] = rhs._first[i];_allocator.construct(_first + i, rhs._first[i]);}_last = _first + len;_end = _first + size;}Vector<T>& operator=(const Vector<T>& rhs) //拷贝构造{if (this == &rhs)return *this;//delete[] _first;for (T* p = _first; p != _last; p++){_allocator.destroy(p); //把first指针指向的数组的有效元素进行析构操作}_allocator.deallocate(_first);//释放堆上的数组内存int size = rhs._end - rhs._first;int len = rhs._last - rhs._first;for (int i = 0; i < len; i++){//_first[i] = rhs._first[i];_allocator.construct(_first + i, rhs._first[i]);}_last = _first + len;_end = _first + size;return *this;}void push_back(const T& val){if (full()){expand();}//*_last = val;_allocator.construct(_last, val);_last++;}void pop_back(){if (empty()){return;}//--_last;--_last;_allocator.destroy(_last);}T back()const //返回容器末尾的元素值{return *(_last - 1);}bool full()const { return _last == _end; }bool empty()const { return _first == _last; }int size()const { return _last - _first; }private:void expand(){int _size = _end - _first;//T* tmp = new T[_size * 2];T* tmp = _allocator.allocate(2 * _size);for (int i = 0; i < _size; i++){//tmp[i] = _first[i];_allocator.construct(tmp + i, _first[i]);}//delete[]_first;for (T* p = _first; p != _last; p++){_allocator.destroy(p);}_allocator.deallocate(_first);_first = tmp;_last = _first + _size;_end = _first + 2 * _size;}T* _first; //指向数组的起始的位置T* _last; //指向数组有效元素的后继位置T* _end; //指向数组空间的后继位置Alloc _allocator;//定义i容器中的空间配置项};
//容器空间分配器
class Test
{
public:Test() { cout << "test()" << endl; }~Test() { cout << "~test()" << endl; }Test(const Test&) { cout << "Test(const Test&)" << endl; }
};int main()
{Test t1, t2, t3;cout << "----------" << endl;Vector<Test>vec;vec.push_back(t1);vec.push_back(t2);vec.push_back(t3);cout << "----------" << endl;vec.pop_back(); //只需要析构cout << "----------" << endl;return 0;
}

在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

Git详解之五:分布式Git

为了便于项目中的所有开发者分享代码&#xff0c;我们准备好了一台服务器存放远程 Git 仓库。经过前面几章的学习&#xff0c;我们已经学会了一些基本的本地工作流程中所需用到的命令。接下来&#xff0c;我们要学习下如何利用 Git 来组织和完成分布式工作流程。 特别是&#…

代码随想录算法训练营第36期DAY24

DAY24 235二叉搜索树的最近公共祖先 迭代法&#xff1a; /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; */class Solutio…

大势所趋!企业网站HTTPS升级全面普及化

JoySSL官网 注册码230918 HTTPS加密协议的应用无疑是维护网络信息安全的重要一环。随着技术的不断进步与用户隐私意识的增强&#xff0c;HTTPS加密已不再仅仅是大型企业的专属&#xff0c;而是逐渐成为所有企业网站的标准配置&#xff0c;其普及化趋势显而易见&#xff0c;堪称…

Kivy UI界面

一、版本介绍 Ubuntu&#xff1a;18.04.6 LTS Conda&#xff1a;4.5.12 Python&#xff1a;3.6.15 Kivy&#xff1a;2.0.0 二、安装Kivy # 更新系统包列表 sudo apt-get update# 安装Kivy的依赖项 sudo apt-get install -y python-pip libsdl2-dev libsdl2-image-dev li…

数据结构之链表篇

今天我们讲我们数据结构的另一个重要的线性结-----链表&#xff0c; 什么是链表 链表是一种在 物理存储上不连续&#xff0c;但是在逻辑结构上通过指针链接下一个节点的形成一个连续的结构。 他和我们的火车相似&#xff0c;我们的元素是可以类比成车厢&#xff0c;需要将⽕…

ubuntu22.04服务器docker-compose方式部署ldap服务

一&#xff1a;系统版本 二&#xff1a;部署环境 节点名称 IP 部署组件及版本 配置文件路径 机器CPU 机器内存 机器存储 Ldap 10.10.10.111 self-service-password:latest phpldapadmin:latest openldap:latest openldap:/data/openldap/config phpldapadmin&#x…

回炉重造java----双列集合(HashMap,TreeMap)

体系结构 ①基本操作: ②遍历方式: 第一种: 键找值&#xff0c;通过map.keySet()获取Map的键集合&#xff0c;通过键去匹配Map中的值 Set<String> strings map.keySet();for (String string : strings) {System.out.println(map.get(string));} 第二种: 键值对&…

【多模态】30、GPT4V_OCR | GPT4V 在 OCR 数据集上效果测评

文章目录 一、背景二、测评2.1 场景文本识别2.2 首先文本识别2.3 手写数学公式识别2.4 图表结构识别&#xff08;不考虑单元格中的文本内容&#xff09;2.5 从内容丰富的文档中抽取信息 三、讨论 论文&#xff1a;EXPLORING OCR CAPABILITIES OF GPT-4V(ISION) : A QUANTITATIV…

Android动态布局framelayout

功能说明 最近碰到一个需求&#xff0c;要求在网页端拖控件&#xff0c;动态配置app控件的模块&#xff0c;大小和位置&#xff0c;显示不同的功能&#xff0c;然后在app大屏展示。 技术难点&#xff1a; 1.动态控件位置和大小难调&#xff0c;会出现布局混乱&#xff0c;位置错…

2024-05-10 C语言使用开源的JPEG解码库libjpeg 读取JPEG文件并将其解码为RGB24格式的数据

一、可以使用开源的JPEG解码库&#xff0c;例如libjpeg库&#xff0c;来读取JPEG文件并将其解码为RGB24格式的数据。 二、在ubuntu上面进行测试。 2.1安装了libjpeg-dev包 sudo apt-get install libjpeg-dev 2.2 测试c源码 #include <stdio.h> #include <stdlib.h&…

虚拟化技术 分离虚拟机数据流量与ESXi的流量管理

一、实验内容 为ESXi主机添加网卡通过vClient查看已添加的网卡信息为ESXi添加网络&#xff0c;创建标准交换机修改网络配置&#xff0c;实现虚拟机数据流量与ESXi的管理流量分离 二、实验主要仪器设备及材料 安装有64位Windows操作系统的台式电脑或笔记本电脑&#xff0c;建…

Java入门基础学习笔记15——强制类型转换

大范围类型的变量是否可以赋值给小范围类型的变量呢&#xff1f; IDEA直接报错。直接报错&#xff0c;是提醒你有问题。但是我非常进行类型转换。 非要强行赋值呢&#xff1f; 强制类型转换&#xff0c;强行将类型范围大的变量&#xff0c;数据赋值给类型范围小的变量。 数据…

实用的Chrome命令 帮你打开Chrome浏览器的隐藏功能

前言 Chrome作为主力浏览器&#xff0c;支持相当丰富的第三方扩展&#xff0c;其实浏览器本身也内置了大量实用的命令。许多实用的功能并没有直接显示在Chrome的菜单上。在这篇文章中&#xff0c;我们将介绍几个实用的chrome:// commands。 通过下面整理的 Chrome 命令&#x…

霍金《时间简史 A Brief History of Time》书后索引(A--D)

图源&#xff1a;Wikipedia INDEX A Abacus Absolute position Absolute time Absolute zero Acceleration Age of the universe Air resistance Albrecht, Andreas Alpha Centauri Alpher, Ralph Anthropic principle Antigravity Antiparticles Aristotle Arrows of time …

权限束缚术--权限提升你需要知道这些

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文主要对渗透测试中权限提升的一些基础知识进行整理 并不包含权限提升的具体操作 适合要入门权限提升的朋友 提权的重要性 我们在渗透网站时&#xff0c;我们往往会拿到一些权限&#xff0c;但是我们的权限有…

全栈开发之路——前端篇(9)插槽、常用api和全局api

全栈开发一条龙——前端篇 第一篇&#xff1a;框架确定、ide设置与项目创建 第二篇&#xff1a;介绍项目文件意义、组件结构与导入以及setup的引入。 第三篇&#xff1a;setup语法&#xff0c;设置响应式数据。 第四篇&#xff1a;数据绑定、计算属性和watch监视 第五篇 : 组件…

【Java代码审计】代码审计的方法及常用工具

【Java代码审计】代码审计的方法及常用工具 代码审计的常用思路代码审计辅助工具代码编辑器测试工具反编译工具Java 代码静态扫描工具 代码审计的常用思路 1、接口排查&#xff08;“正向追踪”&#xff09;&#xff1a;先找出从外部接口接收的参数&#xff0c;并跟踪其传递过…

鸿蒙OpenHarmony开发板解析:【系统能力配置规则】

如何按需配置部件的系统能力 SysCap&#xff08;SystemCapability&#xff0c;系统能力&#xff09;是部件向开发者提供的接口的集合。 开发前请熟悉鸿蒙开发指导文档&#xff1a;gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复制转到。 部件配置系统…

与队列和栈相关的【OJ题】

✨✨✨专栏&#xff1a;数据结构 &#x1f9d1;‍&#x1f393;个人主页&#xff1a;SWsunlight 目录 一、用队列实现栈&#xff1a; 1、2个队列的关联起来怎么由先进先出转变为先进后出&#xff1a;&#xff08;核心&#xff09; 2、认识各个函数干嘛用的&#xff1a; …

android进阶-Binder

参考&#xff1a;Android——Binder机制-CSDN博客 机制&#xff1a;Binder是一种进程间通信的机制 驱动&#xff1a;Binder是一个虚拟物理设备驱动 应用层&#xff1a;Binder是一个能发起进程间通信的JAVA类 Binder相对于传统的Socket方式&#xff0c;更加高效Binder数据拷贝…