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

dede网站栏目管理/外链群发平台

dede网站栏目管理,外链群发平台,黑龙江省建设厅网站,软件设计网站👦个人主页:Weraphael ✍🏻作者简介:目前学习C和算法 ✈️专栏:C航路 🐋 希望大家多多支持,咱一起进步!😁 如果文章对你有帮助的话 欢迎 评论💬 点赞&#x1…

在这里插入图片描述

👦个人主页:@Weraphael
✍🏻作者简介:目前学习C++和算法
✈️专栏:C++航路
🐋 希望大家多多支持,咱一起进步!😁
如果文章对你有帮助的话
欢迎 评论💬 点赞👍🏻 收藏 📂 加关注✨


前言

初阶模板地址:点击跳转

目录

  • 前言
  • 一、typename和class的区别
  • 二、非类型模板参数
      • 2.1 概念
      • 2.2 实际例子:array容器
  • 三、模板特化
      • 3.1 概念
      • 3.2 函数模板特化
      • 3.3 类模板特化
        • 3.3.1 全特化
        • 3.3.2 偏特化
  • 四、模板分离编译问题
      • 4.1 什么是分离编译
      • 4.2 模板的分离编译
      • 4.3 解决方法
  • 五、小结

一、typename和class的区别

在以前博客我们说过,定义模板参数关键字可以用typename,也可以用class,它们是没有区别的,可是真的没有区别吗?来看看以下这个例子

假设要打印容器的数据,要封装一个打印函数(以迭代器的方式)

#include <iostream>
#include <vector>
using namespace std;void Print(const vector<int>& v)
{vector<int>::const_iterator it = v.begin();while (it != v.end()){cout << *it << ' ';it++;}cout << endl;
}int main()
{vector<int> v{ 10,20,30,40,50 };Print(v);return 0;
}

【输出结果】

在这里插入图片描述

以上代码虽然可以正常输出,但它只能打印vector<int>类型容器的数据,若要打印vector<double>,又或者是list容器的数据,那么这样就写死了,有人想可以用函数模板。

代码如下:

#include <iostream>
#include <vector>
using namespace std;// 把class换成typename也是可以的
template<class Container>
void Print(const Container& v)
{Container::const_iterator it = v.begin();while (it != v.end()){cout << *it << ' ';it++;}cout << endl;
}int main()
{vector<int> v{ 10,20,30,40,50 };Print(v);return 0;
}

【输出结果】

在这里插入图片描述

使用函数模板后发现以上代码报错了,提示说需要在Container前加上typename

在这里插入图片描述

那么为什么必须要加上typename呢?

这是因为编译器在编译的时候是从上往下的,当编译到Container::const_iterator it时,Container还没实例化,那么此时编译器区分不了Container是类型还是类对象(静态成员变量Container::const_iterator)。vector<int>是实例化出来的,加上域作用限定符::去找其内嵌类型(迭代器),所以不会报错。因此,编译器要求加上typename告诉Container是类型。

二、非类型模板参数

2.1 概念

模板参数分为:类型形参与非类型形参

  • 类型形参:出现在模板参数列表中,跟在class或者typename之类的参数类型名称。

  • 非类型形参将常量作为类(函数)模板的一个参数,在类(函数)模板中可将该参数当成常量来使用

举个例子:定义一个模板类型的静态数组

#include <iostream>
#include <vector>
using namespace std;// size_t N = 10 - 非类型形参
template<class T, size_t N = 10>
class Array
{
public:T& operator[](size_t index) { return _array[index]; }const T& operator[](size_t index) const { return _array[index]; }size_t size() const { return _size; }bool empty() const { return 0 == _size; }private:T _array[N];size_t _size;
};

需要注意的是,非类型模板参数必须满足以下两点:

  1. 必须是常量,不可被修改
  2. 必须是整型。整型家族有:charshortboolintlonglong long

因此可以得出,非类型模板参数一般是用来定义一个数组的大小的

2.2 实际例子:array容器

在这里插入图片描述

在C++11标准中,引入了一个容器array,它的底层使用了非类型模板参数,是一个真正意义上的泛型数组,这个是用来对标传统数组的。

#include <iostream>
#include <array>
using namespace std;int main()
{int arr[10] = { 0 }; //传统数组array<int, 10> _array; //array容器// 读arr[12];	  _array[12];// 写arr[12] = 0;	_array[12] = 10;return 0;
}

对比传统数组:

  • array也并没有进行初始化。
  • array新数组对于越界读、写检查更为严格。传统数组越界读写,不会发生报错;而array数组则会报错。

虽然对越界行为检查严格 ,但在实际开发中,很少使用array容器,因为它对标传统数组,连初始化都没有,而vector也是类似于数组的容器,在功能和实用性上可以全面碾压,并且 array使用的是栈区上的空间,会存在栈溢出问题,因此可以说array是一个鸡肋的容器。

三、模板特化

3.1 概念

模板特化顾名思义就是对模板(泛型思想)的特殊化处理 。模板特化中分为函数模板特化与类模板特化

通常情况下,使用模板可以实现一些与类型无关的代码,但对于一些特殊类型的可能会得到一些错误的结果,需要特殊处理

比如:实现一个专门用来进行小于比较的函数模板

#include <iostream>
using namespace std;template<class T>
bool Less(T x, T y)
{return x < y;
}int main()
{int a = 1;int b = 2;cout << Less(a, b) << endl; // 可以比较,结果正确int* p1 = &a;int* p2 = &b;cout << Less(p1, p2) << endl; // 可以比较,结果错误return 0;
}

【输出结果】

在这里插入图片描述

上述示例中,p1指向的a显然小于p2指向的b,但是Less内部并没有比较p1p2指向的对象内容,而比较的是p1p2指针的地址。

因此,就需要对模板进行特化。即在原模板函数的基础上,针对特殊类型所进行特殊化的实现方式。

3.2 函数模板特化

函数模板的特化步骤:

  1. 必须要先有一个基础的函数模板
  2. 关键字template后面接一对空的尖括号<>
  3. 函数名后跟一对尖括号,尖括号中指定需要特化的类型
  4. 函数形参必须要和基础的模板函数的基础参数类型完全相同
#include <iostream>
#include <vector>
using namespace std;// 必须要先有一个基础的函数模板
template<class T>
bool Less(T x, T y)
{return x < y;
}// 对Less函数模板进行特化
template<> // 关键字template后面接一对空的尖括号<>
// 函数名后跟一对尖括号,尖括号中指定需要特化的类型
bool Less<int*>(int* x, int* y) // 函数形参必须要和基础的模板函数的基础参数类型完全相同
{return *x < *y;
}int main()
{int a = 1;int b = 2;cout << Less(a, b) << endl; // 可以比较,结果正确int* p1 = &a;int* p2 = &b;cout << Less(p1, p2) << endl; // 可以比较,结果错误return 0;
}

【输出结果】

在这里插入图片描述

不过对于函数模板特化来说,存在一个更加方便的东西:函数重载同样也能解决特殊需求

bool Less(int* x, int* y)
{return *x < *y;
}

3.3 类模板特化

模板特化主要用在类模板中,它可以在泛型思想之上解决大部分特殊问题,并且类模板特化还可以分为:全特化偏特化

3.3.1 全特化

全特化指将原模板参数列表中所有的参数都确定化

注意:在进行全特化前

  1. 需要存在最基本的泛型模板
  2. 全特化模板中的模板参数可以不用写
  3. 需要在类名之后,指明具体的参数类型,否则无法实例化出对象
// 原模板
template<class T1, class T2>
class Test
{
public:Test(const T1& t1, const T2& t2):_t1(t1), _t2(t2){cout << "Test(const T1& t1, const T2& t2)" << endl;}private:T1 _t1;T2 _t2;
};// 全特化后的模
// 将原模板参数列表中所有的参数都确定化
template<>
class Test<int, char>
{
public:Test(const int& t1, const char& t2):_t1(t1), _t2(t2){cout << "Test<int, char>" << endl;}private:int _t1;char _t2;
};int main()
{Test<int, int> T1(1, 2);Test<int, char> T2(20, 'c');return 0;
}

调用时会优先选择更为匹配的类模板

在这里插入图片描述

3.3.2 偏特化

偏特化有以下两种表现方式

  • 部分特化

顾名思义只特化一部分模板参数

// 原模板
template<class T1, class T2>
class Data
{
public:Data() { cout << "Data<T1, T2>" << endl; }private:T1 _d1;T2 _d2;
};// 偏特化// 将第二个参数特化为int
template <class T1>
class Data<T1, int>
{
public:Data() { cout << "Data<T1, int>" << endl; }
private:T1 _d1;int _d2;
};
  • 参数更进一步的限制

不仅仅指特化部分参数,而是针对模板参数的更进一步的条件限制所设计出来的一个特化版本

借助偏特化解决指针无法正常比较问题

class Date
{
public:Date(int year = 1970, int month = 1, int day = 1): _year(year), _month(month), _day(day){}bool operator<(const Date& d)const{return (_year < d._year) ||(_year == d._year && _month < d._month) ||(_year == d._year && _month == d._month && _day < d._day);}bool operator>(const Date& d)const{return (_year > d._year) ||(_year == d._year && _month > d._month) ||(_year == d._year && _month == d._month && _day > d._day);}private:int _year;int _month;int _day;
};//原来的比较模板
template<class T>
class Less
{
public:bool operator()(T x, T y) const{return x < y;}
};//偏特化后的比较模板
template<class T>
class Less<T*>
{
public:bool operator()(T* x, T* y) const{return *x < *y;}
};int main()
{Date d1 = { 2018, 4, 10 };Date d2 = { 2023, 5, 10 };cout << "d1 < d2: " << Less<Date>()(d1, d2) << endl;cout << "&d1 < &d2: " << Less<Date*>()(&d1, &d2) << endl;int a = 1;int b = 2;cout << "&a < &b: " << Less<int*>()(&a, &b) << endl;return 0;
}

在这里插入图片描述

四、模板分离编译问题

4.1 什么是分离编译

一个程序(项目)由若干个源文件共同实现,而每个源文件单独编译生成目标文件,最后将所有目标文件链接起来形成单一的可执行文件的过程称为分离编译模式。

4.2 模板的分离编译

假如有以下场景,模板的声明与定义分离开,在头文件中进行声明,源文件中完成定义:

在这里插入图片描述

【程序结果】

在这里插入图片描述

出现了链接错误!!!

【分析】

代码从文本变为可执行程序所需要的步骤:

  1. 预处理:头文件展开、宏替换、条件编译、删除注释,生成纯净的C/C++代码
  2. 编译:语法/词法/语义分析,错误检查无误后生成汇编代码。注意:头文件不参与编译,编译器对工程中的多个源文件是分离开并且单独编译的
  3. 汇编:生成符号表,生成二进制指令
  4. 链接:将符号表进行合并,并处理地址问题

当模板的声明和定义分离时,在realize.cpp中,由于是 泛型,编译器无法确定函数原型(实例化),因此无法生成函数,也就无法获得函数地址,在进行链接时,无法在符号表中找到目标地址进行跳转,导致链接错误

除了模板以外,还有一个很常见的连接错误,有函数声明,却没有定义

在这里插入图片描述

4.3 解决方法

  1. 将声明和定义放到一个文件(推荐使用这种)
template<class T>
T add(const T x, const T y)
{return x + y;
}
  1. 在函数定义时进行模板特化,编译时生成地址以进行链接(不推荐使用)
template<>
int add(const int x, const int y)
{return x + y;
}

五、小结

模板的优点:

  1. 模板复用了代码,节省资源,更快的迭代开发,C++的标准模板库(STL)因此而产生
  2. 增强了代码的灵活性

模板的缺陷:

  1. 模板会导致代码膨胀问题,也会导致编译时间变长
  2. 出现模板编译错误时,错误信息非常凌乱,不易定位错误

相关文章:

【C++进阶】模板进阶

&#x1f466;个人主页&#xff1a;Weraphael ✍&#x1f3fb;作者简介&#xff1a;目前学习C和算法 ✈️专栏&#xff1a;C航路 &#x1f40b; 希望大家多多支持&#xff0c;咱一起进步&#xff01;&#x1f601; 如果文章对你有帮助的话 欢迎 评论&#x1f4ac; 点赞&#x1…...

Vim如何清空文件

在Vim中&#xff0c;可以使用以下命令清空文件内容&#xff1a; 打开需要清空的文件&#xff1a;在终端中输入vim filename打开文件&#xff0c;其中filename是你要编辑的文件名。 进入命令模式&#xff1a;按下键盘上的Esc键&#xff0c;确保处于Vim的命令模式。&#xff08;…...

问道管理:什么信号?煤飞色舞钢花溅

近期重磅利好不断&#xff0c;对应到A股商场&#xff0c;究竟哪个板块最获益&#xff0c;商场讨论热烈。 地产分析师&#xff1a;方针力度超预期&#xff0c;主张加仓。 银行分析师&#xff1a;存量房贷对银行股心情上的压制完毕&#xff0c;值得重视。 消费分析师&#xff…...

C# PaddleDetection yolo 印章检测

效果 项目 代码 using OpenCvSharp; using OpenCvSharp.Extensions; using Sdcb.PaddleDetection; using Sdcb.PaddleInference; using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq…...

常用框架分析(7)-Flutter

框架分析&#xff08;7&#xff09;-Flutter 专栏介绍Flutter核心思想Flutter的特点快速开发跨平台高性能美观的用户界面 Flutter的架构框架层引擎层平台层 开发过程使用Dart语言编写代码编译成原生代码热重载工具和插件 优缺点优点跨平台开发高性能美观的用户界面热重载强大的…...

清空 Docker 容器的日志文件

删除容器中netcore控制台存储到docker日志记录 在shell命令下执行如下语句&#xff1a; docker ps -aq | xargs docker inspect --format{{.LogPath}} | xargs truncate -s 0 这个命令会执行以下操作&#xff1a; docker ps -aq&#xff1a;列出所有容器的ID&#xff08;包括…...

01-虚拟机安装Windows Server操作系统

1、创建并配置虚拟机 2、安装操作系统 找到windows Server镜像 等待安装 3、设置密码...

应用案例 | 基于三维机器视觉的机器人麻袋拆垛应用解决方案

​Part.1 项目背景 在现代物流和制造行业中&#xff0c;麻袋的拆垛操作是一个重要且频繁的任务。传统的麻袋拆垛工作通常由人工完成&#xff0c;分拣效率较低&#xff0c;人力成本较高&#xff0c;现场麻袋堆叠、变形严重&#xff0c;垛型不规则、不固定&#xff0c;严重影响分…...

1018 Public Bike Management 结题记录(dfs剪枝)

个人觉得直接放入代码是最管用的。 其他方法类似&#xff0c;题意请参考其他博主。 #include <bits/stdc.h> using namespace std; const int N 1e4 50;int maxn 2000000000; int c, n, ed, s[N], m, minlen, needn, backn, pre[N]; bool flag, book[N]; vector<p…...

C++ deque底层原理

deque底层原理 一、目的二、底层实现三、原理图四、类结构五、push_back六、pop_back 一、目的 实现双端数组 二、底层实现 双向开口的连续线性空间 三、原理图 四、类结构 class deque : protected Deque base _Deque_base._Deque_impl M_map 指针数组 _M_map_size …...

打破对ChatGPT的依赖以及如何应对ChatGPT的错误和幻觉

​ OpenAI的ChatGPT是第一个真正流行的生成式AI工具&#xff0c;但它可能不是最好的。现在是时候扩大你的AI视野了。 ChatGPT成为了基于大语言模型(LLM)的聊天机器人的同义词。但是现在是时候停止对ChatGPT的痴迷&#xff0c;开始发现这个新世界中强大的替代品了。 首先&a…...

【git】【IDEA】在idea中使用git

目录 一、 在IDEA中配置git 二、 获取git仓库 2.1 本次初始化仓库 2.2 从远程仓库克隆 三、 本地仓库操作 3.1 将文件加入暂存区 3.2 将暂存区的文件提交到版本库 3.3 快捷键 使用快捷键 实现加入到暂存区与提交到版本库 3.4 查看日志 Show History 四、 远程仓库操…...

【设计模式】装饰者模式

目录 一、定义二、结构三、优点四、使用场景五、代码示例六、截图示例 一、定义 1.在不改变现有对象结构的情况下&#xff0c;动态给该对象添加额外功能的模式 2.类B继承于类A&#xff0c;并将类A作为B类的属性&#xff08;B类聚合A类&#xff09; 3.BufferedInputStream、Buff…...

open cv快速入门系列---数字图像基础

目录 一、数字图像基础 1.1 数字图像和图像单位 1.2 区分图片分辨率与屏幕分辨率 1.3 图像的灰度与灰度级 1.4 图像的深度 1.5 二值图像、灰度图像与彩色图像 1.6 通道数 二、数字图像处理 2.1 图像噪声及其消除 2.2 数字图像处理技术 2.2.1 图像变换 2.2.2 图像增强…...

基础知识回顾:借助 SSL/TLS 和 NGINX 进行 Web 流量加密

原文作者&#xff1a; Robert Haynes 原文链接&#xff1a; 基础知识回顾&#xff1a;借助 SSL/TLS 和 NGINX 进行 Web 流量加密 NGINX 唯一中文官方社区 &#xff0c;尽在 nginx.org.cn 网络攻击者肆无忌惮、作恶多端&#xff0c;几乎每天都有网络入侵、数据窃取或勒索软件攻击…...

iPhone 14 Plus与iPhone 14 Pro:你应该买哪一款

又到了iPhone季,这意味着你可能会在几种不同的机型之间左右为难,无法决定买哪一款。更令人困惑的是,苹果推出的iPhone变体——iPhone 14 Plus,只比老款iPhone 14 Pro低100美元。 有这么多选择,你可能想知道哪款iPhone最适合你。你应该买一部大屏幕的iPhone 14 Plus并节省…...

操作系统清华同步笔记:定义概述+计算机内存和硬盘布局+启动流程顺序+中断、异常和系统调用

定义概述 从用户角度来看&#xff0c;操作系统是一个控制软件&#xff0c;用以管理应用程序&#xff0c;为应用程序提供服务&#xff0c;杀死应用程序等。从内部文件角度来看&#xff0c;操作系统是一个资源管理器&#xff0c;用以管理外设&#xff0c;分配资源。层次结构&…...

uniapp 配置并使用 VueX

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态&#xff0c;并以相应的规则保证状态以一种可预测的方式发生变化。 uni-app 内置了 VueX 1、创建需要的文件 右键点击 根目录【我的是 uni-shop】&#xff0c;然后新建 目录&a…...

vue v-on 艾特@

vue v-on 内联代码&#xff1a; <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><title>Document</titl…...

【Ajax】发送跨域的POST请求时,浏览器会先发送一次OPTIONS请求,然后才发送原本的POST请求

当发送跨域的POST请求时&#xff0c;浏览器会先发送一次OPTIONS请求&#xff0c;这是因为浏览器的同源策略。OPTIONS请求被称为预检请求(pre-flight request)&#xff0c;它是CORS(跨源资源共享)机制中的一部分。 预检请求的目的是为了确保实际请求&#xff08;例如POST、PUT等…...

np.numpy, np.reshape, np.cumsum方法速查

1 np.numpy() 创建一个数组 state[[1,2,3,4,5],[6,7,8,9,10],[11,12,13,14,15]] state2np.array(state) print(state) print(state2)[[1, 2, 3, 4, 5], [6, 7, 8, 9, 10], [11, 12, 13, 14, 15]] [[ 1 2 3 4 5] [ 6 7 8 9 10] [11 12 13 14 15]] 2 np.reshape() 常用于矩阵规…...

七、Kafka-Kraft 模式

目录 7.1 Kafka-Kraft 架构7.2 Kafka-Kraft 集群部署 7.1 Kafka-Kraft 架构 左图为 Kafka 现有架构&#xff0c;元数据在 zookeeper 中&#xff0c;运行时动态选举 controller&#xff0c;由controller 进行 Kafka 集群管理 右图为 kraft 模式架构&#xff08;实验性&#xff…...

jvm开启远程调试功能;idea远程debug

概述 有时候一些问题本地调试无法复现&#xff0c;这个时候可以开启jvm的远程调试功能 jar包启动 jdk8 java -agentlib:jdwptransportdt_socket,address8787,servery,suspendn -jar xxx.jarjdk11/17 java -agentlib:jdwptransportdt_socket,address*:8787,servery,suspe…...

视频汇聚/视频云存储/视频监控管理平台EasyCVR视频平台添加萤火云设备的具体操作步骤

安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快&#xff0c;可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等&#xff0c;以及支持厂家私有协议与SDK接入&#xff0c;包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…...

vue 加载图片不显示

解决vue加载图片不显示问题 加载图片前边加上require require通常用于引入静态资源&#xff0c;如图片、样式文件等。 navList: [{ title: "大盘行情", imgSrc: require ("../../public../../public/imgs/nav1.png") , linkto: "" },{ title: &q…...

Java for循环每次都通过list.size()和 string.length()获取大小性能

有人说在for循环之前用一个局部变量先获取到list.size()、str.length()&#xff0c;然后在for循环的判断条件里通过这个局部变量替换list.size()、str.length()会节省数据计算的时间。事实真的是这样吗&#xff1f;下面就为大家解答这个问题。 说明&#xff1a;此文章针对Andro…...

面试题 08.01. 三步问题

​​题目来源&#xff1a; leetcode题目&#xff0c;网址&#xff1a;面试题 08.01. 三步问题 - 力扣&#xff08;LeetCode&#xff09; 解题思路&#xff1a; 动态规划。1 阶楼梯 1 种走法&#xff0c;2 阶楼梯 2 种走法&#xff0c;3 阶楼梯 6 种类走法。假设有 n(n>3) 阶…...

springboot添加SSL证书,支持https与http

文章目录 一、添加ssl证书二、配置文件三、配置同时支持HTTPS与HTTP四、启动 一、添加ssl证书 将证书文件放在/resource目录下 二、配置文件 修改配置文件 server:ssl:# 指定保存SSL证书的秘钥存储的路径key-store: classpath:dev.cobona.cn.pfx# 访问秘钥存储的密码key-store-…...

【AI】《动手学-深度学习-PyTorch版》笔记(二十):图像增强、微调

AI学习目录汇总 1、图像增强 图像增强可以扩展训练样本数量、减小对某个属性的依赖。比如,裁剪图像,可以减少模型对对象出现位置的依赖;调整亮度、颜色等因素来降低模型对颜色的敏感度等 1.1、准备工作 头文件 %matplotlib inline:图表直接嵌入到Notebook中,本人使用的…...

Vulnhub: Ragnar Lothbrok: 1靶机

kali&#xff1a;192.168.111.111 靶机&#xff1a;192.168.111.226 信息收集 端口扫描 nmap -A -sC -v -sV -T5 -p- --scripthttp-enum 192.168.111.226 作者提示修改hosts文件 目录爆破 gobuster dir -u http://armbjorn -w /usr/share/wordlists/dirbuster/directory-l…...