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

C++感受15-Hello STL 泛型启蒙

  • 生鱼片和STL的关系,你听过吗?
  • 泛型编程和面向对象编程,它们打架吗?
  • 行为泛型和数据泛型,各自的目的是?

泛型启蒙

0 楔

俄罗斯生鱼片,号称俄罗斯版的中国烤鸭,闻名于世。其鱼肉,源于北极海域,传统上用白鱼如omul、nelma 或 muksun 制作,传统上与伏特加搭配,加冰食用,味道柔软、新鲜、冰爽。

虽然我隐约知道前苏联曾经有过一段人民生活物资贫溃的时期,但我还是不太清楚,26岁的Alexander Stepanov 是怎么吃生鱼片,吃到严重中毒,吃到住院,吃到精神恍惚,吃到在心中产生 STL 库的种子……
在这里插入图片描述

1 五段话

五段来自 STL之父 (Alexander Stepanov / 亚历山大・斯特潘诺夫)的话(摘自其多个采访会谈内容)。

  • 谈专业——

“我出生在前苏联的莫斯科。我曾求学于莫斯科国立大学,学习数学。但‘遗憾’的是,我从来都没能成为数学家”

  • 谈程序设计——

“程序设计就像同未理顺的复杂问题打的一场战斗,要打好这场战斗,数学首当其冲,几个世纪以来,数学的作用正在于此。如果将现在生动的数学体系作为实验证据,对于解决人类遇到的复杂性问题,数学还是最有效的”

  • 谈中国——

“中国是一个伟大的国家。曾有过许多伟大的数学家:秦九韶的《数书九章》就是古代数学中的经典……”

  • 谈为什么没成为数学家——

“我实在不能对Tamagawa算术、Coxeter群等一些纯数学的东西感到兴趣” “我想用数学干点实事……”

  • 谈数学专业对编程思想的影响——

“…… 1976年,又要说回到苏联了,我因为吃生鱼片得了严重的食物中毒而住院,在精神恍惚中,我忽然意识到并发的加法计算能力是基于加法是结合性的。同时,我意识到并发的减法运算是和半群结构类型有关联的,这就是最基本的重点:算法是定义于代数结构基础之上的。我又花了一些年头,意识到必须在正规公理上加入复杂性必要条件以扩展结构的概念,接着又花了15年之久才完成全面的架构。我相信迭代器理论是计算科学的中心就象环或Banach区间理论是数学的中心一样。每次当我找到一个算法时,我都要努力去寻求它所定义的结构基础。我想做的就是泛化地描述算法,并乐此不疲。我可以花一个月时间去精确地描述一个众所周知的算法的泛化表示……”

2 课堂视频

我们对 STL,对泛型编程的认识,就从 STL 之父的介绍说起……

C++感受16-Hello STL 泛型启蒙

3 泛型函数

3.1 语法

template <typename T /* 类型参数列表 */>
函数定义

其中函数定义中,可将 T 视为类型名字,可用在函数返回值类型、函数参数、函数体内,比如:

template <typename T>
T add(T a, T b)
{return a + b;  // 相加结果的类型需为 T ,或能隐式转换为 T
}

类型参数列表和函数参数类似,可以有多个参数:

// 一个双类型参数的函数模板,可用于输出带标题的值
tempate <typename S, typename V>
void OutputWithTitle( S const& title, V const& value)
{std::cout << title << " : " << value;
}

3.2 使用

调用者通常通过精准地指定参数类型,为编译器提供准确的类型参数,由编译器在代码需要处,使用明确的类型,替换模板中对应的类型参数(比如上述示例中的 T、S 、V),在编译器自动生成实际函数。由“函数模板”生成的函数,需要时,我们会称它为 “模板函数”。

  • 例一、add 使用
// 调用1, 生成 int add (int a, int b) ...
auto r1 = add (1, 2); // auto 是 C++11 的新语法,此处编译器可推出其为 int // 调用2, 生成 double add (double a, double b) ...
double r2 = add (1.1, 2.0); // 此处的 2.0 不能写成 2// 调用3, 生成 std::string add(std::string a, std::string b) ...
std::string r3 = add(std::string("Hello "), // 明确的std::string 类型std::string("STL") // 同上); // 将返回 "Hello STL"

上述代码将生成三个版本的 add 函数。
其中,r2 例中,如果 2.0 写成 2, 将造成编译器无法判定原模板中唯一的类型参数 T 的实际类型。r3 例中,如果直接传递纯C风格字符串(即字符串祼指针)"Hello " 和 “STL”,将造成编译失败,因为祼的字符串指针,不支持 “相加” 操作。

  • 例二、OutputWithTitle 使用
OutputWithTitle("姓名", "丁小明"); // S和V都是 char const* 类型std::string title = "积分";
double value = 2999.052;
OutputWithTitle(title, value); // S→std::string,V→double;

3.3 auto: C++20 的骚操作

到了 C++20 新标准,一些简单的函数模板定义,可以使用 auto 来简化写法。

比如,经典写法:

template <typename T>
void foo(T v)
{// ...
}

在 20 新标下,可写作:

void foo(auto v)
{// ...
}

注意,如果需要多个参数模板,而每个参数模板都使用 auto 限定类型的话,此时,auto 并不执行 “同一类型” 的限定。比如:

// a , b 都是 auto,但并不存在类型必须一致的限定
auto add(auto a, auto b)
{return a + b;
}// 以下调用成立
auto r = add(900, 99.99); // 返回 999.99

看起来很自由,但如此 “挣脱类型的束缚”,反倒容易滋生程序逻辑错误的恶果。

4. 泛型数据

有些时候——哪怕不是数学家——我们也会更加关心一个类型内部的组成结构,而不太关心(或者可以相对放心地忽略)数据的内部组成的类型。

比如,一个数学软件,可能希望有个类型,可以表示二维笛卡尔坐标(Cartesian coordinates)中的二维直角坐标点,不关心其中的x, y 坐标采用哪种类型。

像“不关心”,或 “随便”这样的用语,记得要反过来理解,它们的真实意思不是真的不在乎,面是:“干嘛分这分那?我都要!”。

template <typename T>
struct Point
{T x, y; // 用 T 表示 x, y 将来的真实类型,二者一致
};

和函数模板自动推理出函数略有不同,实际使用中,类的模板转换成类时,通常需要在类(class或struct)之后带上 ,其中 T 用于明确指定所需模板参数的真实类型。

// 使用 int 实例化类模板
Point<int> p1; 
p1.x = 10// 可将 float 赋 .y,只是转换过程中小数位会丢失
p1.y = 9.8f; // 使用 float 实例
Point<float> p2; 
p2.x = 99.f;
p2.y = 100; // 同样,此时不存在语法错误

以上示例中,之所以能跨类型赋值,是因为此时无论 p1 还是 p2 ,内部的 x, y 的类型都已经明确指定了。

定义类模板时,各类型参数既可用于指定成员数据的类型,也可用在成员方法(包括构造、析构等)身上(返回值、入参、函数内临时变量定义等等):

template <typename T>
struct Point
{T x, y;Point() = default; // 默认构造 C++11语法Point(T x, T y): x(x), y(y) // 成员数据初始化列表{}// 让 x, y 各自增加指定的长度void IncBy (T dx, T dy){x += dx;y += dy;}
};

构造、成员数据初始化列表知识点,讲 见《Hello Object 封装版.下》 等课堂。

注意,Point的第二个构造函数,和 IncBy() 成员函数都用到了 T,它就是定义类模板时的那个T,无需在函数自身加 template <typename > 作定义。

继续本体不包含 ,当构造函数使用到所在类模板的类型参数,并且,构造对象时的入参,能明确的,完整地推后出类模板的所有模板参数,则从 17 新标开始,定义对象时,不显示指定类模板的类型入参(全部或部分),也是可行的,比如:

Point p3 (99, 100); // 相当于 Point<int>
Point p4 (99.0, 100.0); // 相当于 Point<double>
Point p5 (std::string("90"), std::string("12.345")); // 虽然奇怪,但也合法

我们当然举双手双脚反对 p5 的类型 Point<std::string> ,试想对它调用 IncBy(“哦”, “哈”)之后……

5 初窥 vector

vector 翻译为 “矢量”,它是 STL 中最经典的的一个数据容器类(模板)。请阅读以下示例代码,在下一节课一上课,我们就来完善它:

#include <vector>using namespace std;struct 鸡精 { void 忍耐() { cout << "欢迎品尝!\n"; } };
struct 象妖 { void 愤怒() { cout << "大胆!可笑!!\n"; } };int main()
{   vector<鸡精> v1; // 鸡精专用瓶vector<象妖> v2; // 象妖专用瓶std::cout << "妖怪!我叫你一声,你可敢答应?\n";...鸡精 sj1;v1.push_back(sj1);象妖 dx1;v2.push_back(dx1);...
}

只是看可学不会编程哦,像 STL 这样的库更是需要动手实践。谁出题?有专业的,一线编程多年的同行为你出题,为你批改,欢迎到本课原发站 www.d2school.com 做作业,提问,扎实扎实踏出编程学习的每一步,看似“劳累”,但这么做的,你会获得更快的进步。

作业示例

相关文章:

C++感受15-Hello STL 泛型启蒙

生鱼片和STL的关系&#xff0c;你听过吗&#xff1f;泛型编程和面向对象编程&#xff0c;它们打架吗&#xff1f;行为泛型和数据泛型&#xff0c;各自的目的是&#xff1f; 0 楔 俄罗斯生鱼片&#xff0c;号称俄罗斯版的中国烤鸭&#xff0c;闻名于世。其鱼肉&#xff0c;源于…...

【Java 学习】对象赋值的艺术:Java中clone方法的浅拷贝与深拷贝解析,教你如何在Java中实现完美复制

&#x1f4ac; 欢迎讨论&#xff1a;如对文章内容有疑问或见解&#xff0c;欢迎在评论区留言&#xff0c;我需要您的帮助&#xff01; &#x1f44d; 点赞、收藏与分享&#xff1a;如果这篇文章对您有所帮助&#xff0c;请不吝点赞、收藏或分享&#xff0c;谢谢您的支持&#x…...

基于高斯混合模型的数据分析及其延伸应用(具体代码分析)

一、代码分析 &#xff08;一&#xff09;清除工作区和命令行窗口 clear; clc;clear;&#xff1a;该命令用于清除 MATLAB 工作区中的所有变量&#xff0c;确保代码运行环境的清洁&#xff0c;避免之前遗留的变量对当前代码运行产生干扰。例如&#xff0c;如果之前运行的代码中…...

无人机+Ai应用场景!

军事领域 无人机AI制导技术在军事领域的应用尤为突出。通过AI技术&#xff0c;无人机可以自主执行侦察、监视、打击等多种任务&#xff0c;极大地提高了军事行动的效率和准确性。 侦察与监视&#xff1a;AI无人机能够利用先进的传感器和摄像头&#xff0c;对目标区域进行大范…...

操作手册:集成钉钉审批实例消息监听配置

此文档将记录在慧集通平台怎么实现钉钉审批实例结束或发起或取消时&#xff0c;能够实时的将对应的实例数据抓取出来送入第三方系统 集成平台配置 1、配置中心库&#xff0c;存储钉钉发送的消息&#xff0c;可以忽略&#xff0c;若不配置&#xff0c;则钉钉的消息将不再记录到…...

AI大模型-提示工程学习笔记4

卷首语&#xff1a;我所知的是我自己非常无知&#xff0c;所以我要不断学习。 写给AI入行比较晚的小白们&#xff08;比如我自己&#xff09;看的&#xff0c;大神可以直接路过无视了。 不同主题提示词可以完成不同基本任务&#xff0c;常见的提示主题有&#xff1a; 文本概…...

Vue3.5 企业级管理系统实战(一):项目初始搭建与配置

本文详细介绍了如何使用 Vite 构建一个高效的 Vue 3.5 项目框架&#xff0c;并整合了 ESLint、Prettier、EditorConfig、Husky、lint-staged 和 commitlint 等现代化开发工具。通过这些工具的集成&#xff0c;我们能够确保代码质量、格式化和提交规范的一致性&#xff0c;从而提…...

缓存-Redis-缓存更新策略-主动更新策略-Cache Aside Pattern(全面 易理解)

**Cache-Aside Pattern&#xff08;旁路缓存模式&#xff09;**是一种广泛应用于缓存管理的设计模式&#xff0c;尤其在使用 Redis 作为缓存层时尤为常见。该模式通过在应用程序与缓存之间引入一个旁路&#xff0c;确保数据的一致性和高效性。本文将在之前讨论的 Redis 主动更新…...

杭州市有哪些大学能够出具论文检索报告?

杭州市具有查收查引服务的学校有浙江大学、杭州电子科技大学、浙江工业大学、杭州师范大学等高校。 1、浙江大学图书馆 浙江大学图书馆提供文献查收查引服务&#xff0c;包括查询学术论文被SCIE、SSCI、A&HCI、EI、CPCI-S、CPCI-SSH、CSSCI、CSCD等国内外权威数据库收录和…...

SpringBootWeb 登录认证(day12)

登录功能 基本信息 请求参数 参数格式&#xff1a;application/json 请求数据样例&#xff1a; 响应数据 参数格式&#xff1a;application/json 响应数据样例&#xff1a; Slf4j RestController public class LoginController {Autowiredpriva…...

使用AOP在切面逻辑中无法获取到requesetBody

使用场景&#xff1a;在接口处理之前&#xff0c;我们需要拿到请求参数&#xff0c;对参数进行校验。注意&#xff0c;这里需要拿到的是原始的请求信息&#xff01; 一般的获取方式 ServletInputStream inputStream request.getInputStream(); StringBuilder stringBuilder …...

生成模型:变分自编码器-VAE

1.基本概念 1.1 概率 这里有&#xff1a; x为真实图像&#xff0c;开源为数据集, 编码器将其编码为分布参数 x ^ \hat{x} x^为生成图像, 通过解码器获得 p ( x ) ^ \hat{p(x)} p(x)^​: 观测数据的分布, 即数据集所构成的经验分布 p r e a l ( x ) p_{real}(x) preal​(x): …...

Hive sql执行文件合并配置参数

HIVE自动合并输出的小文件的主要优化手段为&#xff1a;HIVE将会启动一个独立的map-reduce任务进行输出文件的merge。 set hive.merge.mapfiles true&#xff1a; 在只有map的作业结束时合并小文件&#xff0c; set hive.merge.mapredfiles true&#xff1a; 在Map-Reduce的任…...

鸿蒙 ArkUI实现地图找房效果

常用的地图找房功能&#xff0c;是在地图上添加区域、商圈、房源等一些自定义 marker&#xff0c;然后配上自己应用的一些筛选逻辑构成&#xff0c;在这里使用鸿蒙 ArkUI 简单实现下怎么添加区域/商圈、房源等 Marker. 1、开启地图服务 在华为开发者官网&#xff0c;注册应用&…...

一套极简易的直流无刷电机(Deng FOC)开发套件介绍

目录 概述 1. 硬件组成介绍 1.1 主要硬件 1.2 电机驱动板介绍 1.3 2208电机模块 1.3.1 参数介绍 1.3.2 认识2208电机 2 驱动板接口介绍 2.1 PCB接口&#xff08;MCU&#xff09;定义 2.2 功能描述 2.2.1 电机驱动接口 2.2.2 编码器接口 2.2.3 电流输入引脚接口 2.…...

Inception模型详解及代码分析

模型背景 Inception系列模型由Google团队提出,旨在解决CNN分类模型面临的两大挑战: 如何在增加网络深度的同时提升分类性能 如何在保证分类准确率的同时降低计算和内存开销 Inception V1通过引入 并行卷积结构 和 1x1卷积 ,巧妙地解决了这两个问题,在保证模型质量的前提下…...

Springboot AOP 每个接口运行前 修改入参

控制台log输出为何频频失踪?   wxss代码为何频频失效?   wxml布局为何乱作一团?   究竟是道德的沦丧?还是人性的缺失?   让我们一起来 走 跑进科学 前言 麻蛋被这个功能恶心好久 终于解决了 特此记录一下 正文 Before("authCut()")public void cutProc…...

课题推荐——基于GPS的无人机自主着陆系统设计

关于“基于GPS的无人机自主着陆系统设计”的详细展开&#xff0c;包括项目背景、具体内容、实施步骤和创新点。如需帮助&#xff0c;或有导航、定位滤波相关的代码定制需求&#xff0c;请点击文末卡片联系作者 文章目录 项目背景具体内容实施步骤相关例程MATLAB例程python例程 …...

【深度学习】在深度学习训练过程中,数据量太少会导致模型过拟合还是欠拟合?

过拟合与欠拟合 过拟合 : 是指在训练集上表现非常好&#xff0c;但是在新的数据集上表现较差的现象。具体来说&#xff0c;模型在训练集上过度学习&#xff0c;捕捉了数据中的噪声和偶然性&#xff0c;导致它对训练数据的拟合非常精确&#xff0c;但缺乏泛化能力&#xff0c;无…...

js迭代器模式

以前JS原生的集合类型数据结构&#xff0c;只有Array&#xff08;数组&#xff09;和Object&#xff08;对象&#xff09;&#xff1b; 而ES6中&#xff0c;又新增了Map和Set。四种数据结构各自有着自己特别的内部实现&#xff0c;但我们仍期待以同样的一套规则去遍历它们&…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

51c自动驾驶~合集58

我自己的原文哦~ https://blog.51cto.com/whaosoft/13967107 #CCA-Attention 全局池化局部保留&#xff0c;CCA-Attention为LLM长文本建模带来突破性进展 琶洲实验室、华南理工大学联合推出关键上下文感知注意力机制&#xff08;CCA-Attention&#xff09;&#xff0c;…...

React hook之useRef

React useRef 详解 useRef 是 React 提供的一个 Hook&#xff0c;用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途&#xff0c;下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例

一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

Day131 | 灵神 | 回溯算法 | 子集型 子集

Day131 | 灵神 | 回溯算法 | 子集型 子集 78.子集 78. 子集 - 力扣&#xff08;LeetCode&#xff09; 思路&#xff1a; 笔者写过很多次这道题了&#xff0c;不想写题解了&#xff0c;大家看灵神讲解吧 回溯算法套路①子集型回溯【基础算法精讲 14】_哔哩哔哩_bilibili 完…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

《用户共鸣指数(E)驱动品牌大模型种草:如何抢占大模型搜索结果情感高地》

在注意力分散、内容高度同质化的时代&#xff0c;情感连接已成为品牌破圈的关键通道。我们在服务大量品牌客户的过程中发现&#xff0c;消费者对内容的“有感”程度&#xff0c;正日益成为影响品牌传播效率与转化率的核心变量。在生成式AI驱动的内容生成与推荐环境中&#xff0…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

新能源汽车智慧充电桩管理方案:新能源充电桩散热问题及消防安全监管方案

随着新能源汽车的快速普及&#xff0c;充电桩作为核心配套设施&#xff0c;其安全性与可靠性备受关注。然而&#xff0c;在高温、高负荷运行环境下&#xff0c;充电桩的散热问题与消防安全隐患日益凸显&#xff0c;成为制约行业发展的关键瓶颈。 如何通过智慧化管理手段优化散…...