【C++】——模板初阶 | STL简介

news2024/12/23 13:53:53

在这里插入图片描述

前言:
模板初阶 | STL简介


文章目录

  • 一、模板初阶
    • 1.1 函数模板
    • 1.2 类模板
  • 二、STL简介 (了解)

一、模板初阶

泛式编程(Generic Programming)指的是一种编程范式,其核心思想是编写可以在不同数据类型上通用的代码,从而提高代码的复用性、可维护性和可扩展性。

泛式编程的实现方式包括模板(Template)和泛型(Generics)。在C++中,使用模板可以实现泛型编程,而在Java、C#等语言中,则使用泛型来实现类似的功能。


1.1 函数模板

函数模板的格式如下:

template <typename T1,typename T2,......,typename Tn>
返回类型 函数名(参数列表) {
    // 函数体
}
  • template <typename T1,typename T2,......,typename Tn>:以关键字 template 开始,后跟尖括号 < >,里面是一个或多个模板参数的列表。例如typename T1 定义了一个类型模板参数 T1,可以替换为其他任意合法的标识符。

  • 返回类型:函数的返回类型,可以是任意类型。

  • 函数名:函数的名称,可以是任意合法的标识符。

  • 参数列表:函数的参数列表,可以包含零个或多个参数,每个参数可以是任意合法的标识符,也可以是模板参数。

  • 函数体:函数的具体实现,包括函数的操作和逻辑。

一个具体的函数模板示例:

// 函数模板的定义
template <typename T>
T maximum(T x, T y) {
    return (x > y) ? x : y;
}

// 调用模板函数
int result1 = maximum(10, 20);
double result2 = maximum(3.14, 2.71);

在编译器编译阶段,对于模板函数的使用,编译器需要根据传入的实参类型来推演生成对应类型的函数以供调用。比如:当用double类型使用函数模板时,编译器通过对实参类型的推演,将T确定为double类型,然后产生一份专门处理double类型的代码,对于字符类型也是如此。


函数模板实例化
函数模板的实例化是指根据具体的类型,生成模板函数的过程。当编译器在代码中遇到对函数模板的调用时,它会根据传递的参数类型推导出模板参数的具体类型,并生成相应的函数实例。

// 定义函数模板
template <typename T>
T maximum(T x, T y) {
    return (x > y) ? x : y;
}

int main() {
    int result1 = maximum(10, 20); // 实例化为 maximum<int>(10, 20),T 被推导为 int
    double result2 = maximum(3.14, 2.71); // 实例化为 maximum<double>(3.14, 2.71),T 被推导为 double

	 //或者我们可以手动进行实例化
	 // 手动实例化模板函数为 int 类型
    int result3 = maximum<int>(10, 20);
    
     // 手动实例化模板函数为 double 类型
    double result4 = maximum<double>(3.14, 2.71);

    return 0;
}

函数模板的实例化是在编译时进行的,每次调用函数模板时,都会根据传递的参数类型生成相应的函数实例。这样,同一个函数模板可以用于多种不同类型的参数,实现了通用的函数。


模板参数的匹配原则
一个非模板函数和一个同名的函数模板可以同时存在,编译器会根据一定的匹配规则来确定使用哪一个函数。

  1. 如果函数调用的参数列表与非模板函数的参数列表精确匹配,那么将调用非模板函数。
  2. 如果函数调用的参数列表可以匹配到函数模板的模板参数类型,并且生成一个能够匹配的实例化函数,那么将调用函数模板的实例化版本。

例如:

// 非模板函数
void foo(int x) {
    cout << "Non-template function: " << x << endl;
}

// 函数模板
template <typename T>
void foo(T x) {
    cout << "Function template: " << x << endl;
}

int main() {
    foo(42); // 调用非模板函数
    foo("hello"); // 调用函数模板
    return 0;
}

在这个例子中,调用 foo(42) 时会匹配到非模板函数 foo(int),因为参数类型 int 精确匹配。而调用 foo("hello") 时会匹配到函数模板 foo(T),并实例化为 foo(const char*),因为函数模板的模板参数可以匹配到参数类型 const char*


1.2 类模板

除函数模板外,类模板是C++中另一个重要的模板形式,允许定义通用的类,其中的某些成员类型或成员函数可以由用户指定。类模板以 template <typename T>template <class T> 开始,后跟着类的定义,其中 T 是一个占位符类型,表示任意类型。

例如我们创建一个类,类的对象的类型可能是int或者char等等:

template <class T, int N>
class Stack {
private:
    T elements[N];
    int top; // 栈顶索引
public:
    Stack() : top(-1) {} // 初始化栈顶索引为-1

    void push(const T& element) {
        if (top == N - 1) {
        	// 栈满,抛异常
            throw std::overflow_error("Stack<>::push(): stack overflow");
        }
        elements[++top] = element; // 将元素入栈
    }
};

这个示例中,Stack 是一个类模板,有两个模板参数:T 表示元素的类型,N 表示栈的最大容量。

//类模板实例化
Stack<int, 10> intStack; // 创建一个最大容量为 10 的整型栈
Stack<double, 5> doubleStack; // 创建一个最大容量为 5 的双精度浮点型栈

当类模板中的函数定义放在类外部时,如果函数使用了类模板的模板参数,那么函数定义必须在其前面加上模板参数列表,并且在函数名之后使用类模板的模板参数,以表明该函数是属于类模板的。

例如:

template <typename T>
class Stack {
public:
    void push(const T& element); // 函数声明
};

// 函数定义放在类外部
template <typename T>
void Stack<T>::push(const T& element) {
    // 函数定义
}

二、STL简介 (了解)

STL 是 C++ 标准模板库(Standard Template Library)的缩写。它是 C++ 标准库的一部分,提供了一系列的通用模板类和函数,用于实现各种常见的数据结构和算法,例如向量(vector)、链表(list)、栈(stack)、队列(queue)、集合(set)、映射(map)等,以及对这些数据结构进行操作的算法,如排序、查找、遍历等。

STL 的设计思想是基于泛型编程(Generic Programming),它使用模板技术实现通用性和灵活性,使得用户能够在不同的数据类型上使用相同的算法和数据结构。STL 提供了大量的模板类和函数,使得程序员可以在开发过程中更加高效地处理各种数据结构和算法问题。

STL(Standard Template Library)的六大组件:
在这里插入图片描述

  1. 容器(Containers)
    容器是用于存储和管理数据的数据结构,包括向量(vector)、链表(list)、双端队列(deque)、队列(queue)、栈(stack)、集合(set)、映射(map)等。每种容器都有不同的特点和适用场景,可以根据具体的需求选择合适的容器。

  2. 算法(Algorithms)
    算法是用于对容器中的元素进行操作和处理的函数,包括排序、查找、遍历、拷贝、删除等一系列操作。STL提供了大量的算法,能够满足各种不同的需求,提高代码的复用性和可读性。

  3. 迭代器(Iterators)
    迭代器是一种用于遍历容器中元素的对象,它提供了统一的访问接口,使得算法能够与容器解耦合。STL提供了多种类型的迭代器,包括输入迭代器、输出迭代器、正向迭代器、双向迭代器和随机访问迭代器,每种迭代器都有不同的功能和特点。

  4. 仿函数(Functors)
    仿函数是一种可调用对象,它可以像函数一样被调用,并且可以作为算法的参数使用。仿函数可以是普通函数指针、函数对象(重载了函数调用运算符 operator() 的类对象)、Lambda 表达式等。STL提供了一些内置的仿函数,同时也支持用户自定义的仿函数。

  5. 适配器(Adapters)
    适配器是一种用于在不同容器之间进行转换和包装的机制,它可以将一个容器转换为另一个容器,或者在一个容器的基础上提供新的功能。STL提供了一些常用的适配器,如栈适配器(stack)、队列适配器(queue)、优先队列适配器(priority_queue)等。

  6. 配置器(Allocators)
    配置器是一种用于内存管理的机制,它控制着容器在内存中的分配和释放。STL中的容器和算法都使用了配置器来进行内存管理,但配置器的具体实现通常是由编译器提供的默认配置器。STL也允许用户自定义配置器,以满足特定的需求。

这些六大组件构成了STL的核心部分,它们共同组成了一个功能强大、高效易用的库,为C++程序员提供了丰富的数据结构和算法,极大地提高了程序开发的效率和质量。


在这里插入图片描述
如果你喜欢这篇文章,点赞👍+评论+关注⭐️哦!
欢迎大家提出疑问,以及不同的见解。

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

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

相关文章

真的是性能优化(压测)-纯思想

文章目录 概要优化指标-MD都是文字看看就行性能优化操作1、代码优化&#xff1a;2、系统配置与环境优化&#xff1a;3、架构与设计&#xff1a;4、~~实施与监控&#xff1a;~~5、~~开发流程和环境管理&#xff1a;~~ 总结 概要 性能优化是一个持续的过程&#xff0c;需要监控、…

如何管理Windows Server磁盘分区?

Windows Server系统内置的分区软件有哪些&#xff1f; 系统内置的Windows Server分区管理软件主要分为两个——磁盘管理工具和Diskpart命令。其中磁盘管理工具可以帮助人们进行基础的磁盘、分区或卷管理任务&#xff0c;Diskpart命令则是在命令提示符中使用命令行来管理磁盘分…

如何将新标注的三元组数据转换成unicoqe可以处理的格式

目录 问题描述: 问题解决: 问题描述: 原始的标注的三元组格式如下: 需要转换的格式如下: tips:有一个小的难点: 1. 针对多三元组的情况,需要额外考虑 2. 最后一个样本,也记得需要处理

QEMU之CPU虚拟化

概述 KVM是由以色列初创公司Qumranet在CPU推出硬件虚拟化之后开发的一个基于内核的虚拟机监控器。 KVM是一个虚拟化的统称方案&#xff0c;除了x86外&#xff0c;ARM等其他架构也有自己的方案&#xff0c;所以KVM的主体代码位于内核树virt/kvm目录下面&#xff0c;表示所有CP…

JUC并发编程最新面试题(持续更新)

JUC并发编程 1 并发编程的优缺点为什么要使用并发编程&#xff08;并发编程的优点&#xff09; 充分利用多核CPU的计算能力&#xff1a;通过并发编程的形式可以将多核CPU 的计算能力发挥到极致&#xff0c;性能得到提升方便进行业务拆分&#xff0c;提升系统并发能力和性能&a…

服务器被黑该如何查找入侵痕迹以及如何防御攻击

当公司的网站服务器被黑&#xff0c;被入侵导致整个网站&#xff0c;以及业务系统瘫痪&#xff0c;给企业带来的损失无法估量&#xff0c;但是当发生服务器被攻击的情况&#xff0c;作为服务器的维护人员应当在第一时间做好安全响应&#xff0c;对服务器以及网站应以最快的时间…

深入了解Git

1.1 Git 的工作流程简介 克隆 Git 资源作为工作目录 在克隆的资源上添加或修改文件 如果其他人修改了&#xff0c;你可以更新资源 在提交前查看修改 提交修改 在修改完成后&#xff0c;如果发现错误&#xff0c;可以撤回提交并再次修改并提交 1.2 Git 工作区、暂存区和版…

86、移除推理路径上的所有内存操作

动态申请内存的影响,前两节已经介绍过了,细心的朋友可能会发现,在使用 C++实现的 resnet50 代码中,还存在一处动态申请内存的操作。 那就是对于每一层的输入或输出 feature map 数据进行内存申请,比如在 3rd_preload/ops/conv2d.cc 文件中,卷积的计算中存在对于输出 fea…

postgresql矢量切片坐标转换的ST_AsMVTGeom函数使用

一、函数签名 geometry ST_AsMVTGeom(geometry geom, box2d bounds, integer extent4096, integer buffer256, boolean clip_geomtrue); 二、描述 将一个图层中位于参数box2d范围内的一个几何图形的所有坐标转换为MapBox VectorTile坐标空间里的坐标。 该函数会尽量保持、甚至纠…

Excel Ctrl + G快捷键快速标记不同

一. 需求 如下图所示&#xff0c;水果的预计销量和实际销量存在差异&#xff0c;现在想把与预计销量不同的实际销量标记出来。 二. Ctrl G 快捷键 ⏹如下图所示&#xff0c;先选中比较区域后&#xff0c;按下Ctrl G快捷键调出定位条件面板&#xff0c; 然后选择行内容差异…

PostgreSQL 的实体化视图介绍

PostgreSQL 实体化视图提供一个强大的机制&#xff0c;通过预先计算并将查询结果集存储为物理表来提高查询性能。本教程将使用 DVD Rental Database 数据库作为演示例子&#xff0c;指导你在 PostgreSQL中创建实体化视图。 了解实体化视图 实体化视图是查询结果集的快照&…

盘点全网好用的ai伪原创工具

在信息内容发展的今天&#xff0c;写作在我们每个人的生活当中息息相关。可能写作对于有的人来说很简单&#xff0c;但对于有些人来说可能也会很难&#xff0c;幸运的是&#xff0c;我们在这个技术发达的今天&#xff0c;对于很多难题都是可以迎刃而解的&#xff0c;即使对于那…

arcgisPro制图输出

1、设置地图底图 2、导入数据 3、 设置图形颜色&#xff0c;如下&#xff1a;右键“浙江省”数据层&#xff0c;选择符号系统 4、在右侧可看到打开的符号系统栏&#xff0c;进行如下设置: 5、移除“其他所有值”项&#xff0c;如下&#xff1a; 6、设置图形轮廓&#xff0c;如下…

300分钟吃透分布式缓存-11讲:MC如何淘汰冷key和失效key?

淘汰策略 Mc 作为缓存组件&#xff0c;意味着 Mc 中只能存储访问最频繁的热数据&#xff0c;一旦存入数据超过内存限制&#xff0c;就需要对 Mc 中的冷 key 进行淘汰工作。Mc 中的 key 基本都会有过期时间&#xff0c;在 key 过期后&#xff0c;出于性能考虑&#xff0c;Mc 并…

创新性3D数据合成模型,微软推出EgoGen

随着AR、VR等设备的广泛应用,第一人称的应用开始增多。但在研发方面面临不同的挑战,例如&#xff0c;图像模糊、视觉混乱、遮挡更严重等&#xff0c;给视觉模型的训练带来重大挑战。 一方面,人工标注真实第一视角数据集&#xff0c;来培训深度学习模型的成本和难度都很高。另一…

Python基于PyQt打包一个exe应用程序

一、环境搭建 1、安装python地三方库 pip install PyQt5 pip install pyqt5-tools pip install pyinstaller 2、下载并安装Qt Designer 下载地址:https://build-system.fman.io/qt-designer-download 二、QT Design使用 1、控件布局 2、布局好之后保存文件,Ctrl+s 保存为…

时域系统到频域响应的直观解析及数学推导

课本里经常有已知系统时域的差分方程&#xff0c;求系统的频率响应这样的题&#xff0c;老师会讲怎么带公式进去解决&#xff0c;怎么查表解决&#xff0c;但我们总时无法直观地理解这两种转换的特殊关联在哪里&#xff0c;这篇文章以FIR滤波器为例&#xff0c;不仅列出了课本里…

Nginx网络服务二-----(虚拟机和location)

一、HTTP设置 1.设置虚拟主机 1.1Nginx 基于域名---虚拟主机 include /apps/nginx/conf.d/*.conf; 1.2Nginx 基于端口---虚拟主机 在做了域名的基础上&#xff0c;按照以下步骤继续 1.3Nginx 基于IP---虚拟主机 2.server下的root root路径格式 指定文件的路径 url …

集合、List、Set、Map、Collections、queue、deque

概述 相同类型的数据进行统一管理操作&#xff0c;使用数据结构、链表结构&#xff0c;二叉树 分类&#xff1a;Collection、Map、Iterator 集合框架 List接口 有序的Collection接口&#xff0c;可以对列表中的每一个元u尿素的插入位置进行精确的控制&#xff0c;用户可以根…

【Django】Django自定义后台表单——对一个关联外键对象同时添加多个内容

以官方文档为例&#xff1a; 一个投票问题包含多个选项&#xff0c;基本的表单设计只能一个选项一个选项添加&#xff0c;效率较低&#xff0c;如何在表单设计中一次性添加多个关联选项&#xff1f; 示例代码&#xff1a; from django.contrib import adminfrom .models impo…