C++ 提高编程

C++ 提高编程
主要针对C++泛型编程和STL技术

一、 模板
1、 概念
模板就是建立通用的模具,大大提高代码的复用性

模板特点

模板不可以直接使用,它只是一个框架
​ 模板的通用并不是万能的
2、 函数模板
C++ 另一种编程思想为泛型编程,主要利用的技术就是模板
C++ 提供两种模板机制:函数模板 和 类模板
2.1 函数模板语法
函数模板的作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体确定,用一个虚拟的类型来代表

语法

template<typename T>
函数声明或定义

参数

template:声明创建模板
typename:表明其后面的符号是一种数据类型,可以用class来代替
T:通用的数据类型,名称可以替换,通常为大写字母

// 两个整型交换函数
void swap(int& a, int& b)
{int temp = a;a = b; b = temp;
}
// 交换浮点型的函数
void swap(double& a, double& b)
{double temp = a;a = b;b = temp;
}
// 函数模板
template <typename T>  // 声明模板,告诉编译器后面代码紧跟着T,不要报错,T是一个通用的数据类型
void m_swap(T& a, T& b)
{T temp = a;a = b;b = temp;
}
void test()
{int a = 1;int b = 3;double a1 = 4;double b1 = 5;/* swap(a, b);cout << a << b << endl;swap(a1, b1);cout << a1 << b1 << endl; */// 使用函数模板// 1、 自动推导m_swap(a, b);cout << a << b << endl;// 2、 显示指定类型m_swap<int>(a, b);cout << a << b << endl;
}

模板可以将数据类型参数化

模板的使用方法

自动推导
显示指定类型
2.2 注意事项
注意事项

自动推导数据类型,必须推导出一致的数据类型 T,才可以使用
模板必须要确定出 T 的数据类型,才可以使用
2.3 普通函数和函数模板的区别
普通函数调用时可以发生自动类型转换(隐式类型装换)
函数模板调用时,如果利用自动类型推导,不会发生隐式类型装换
如果利用显示指定类型的方法,可以发生隐式类型转换
2.4 普通函数和函数模板的调用规则
调用规则如下

如果函数模板和普通函数都可以实现,优先调用普通函数

可以通过空模板参数列表强制调用函数模板

void myPrint(int a, int b)
{cout << a << b << endl;cout << "普通函数" << endl;
}
template<typename T>
void myPrint(T a, T b)
{cout << a << b << endl;cout << "模板函数" << endl;
}void test()
{int a = 10;int b = 20;myPrint<>(a, b);  // 空模板参数列表调用模板函数
}

函数模板也可以发生重载

如果函数模板可以产生更好的匹配模式,优先调用函数模板

void myPrint(int a, int b)
{cout << a << b << endl;cout << "普通函数" << endl;
}
template<typename T>
void myPrint(T a, T b)
{cout << a << b << endl;cout << "模板函数" << endl;
}void test()
{char a = 'a';char b = 'b';myPrint(a, b);  // 函数模板可以产生更好的匹配 
}

既然提供了函数模板,最好不要提供普通函数,否则容易出现二义性

2.5 模板的局限性
模板的通用性并不是万能的
如果传入的是一个元组以及自定义数据类型,就无法实现了

因此,C++为了解决这种问题,提供模板的重载,可以为这些特定的类型提供具体化模板

// 模板重载
// 对比两个数据是否相等
class Person
{
public:Person(string name, int age){m_Age = age;m_Name = name;}string m_Name;int m_Age;
};
template<class T>
bool myCompare(T& a, T& b)  // 如果传入的是一个自定义数据类型呢
{if (a == b){return true;}else{return false;}
}
// 利用具体化Person的版本实现代码,具体化优先调用
// 也可以使用运算符重载
template<>bool myCompare(Person& p1, Person& p2)
{if (p1.m_Name == p2.m_Name && p1.m_Age == p2.m_Age){return true;}else{return false;}
}
void test()
{Person p1("Tom", 10);Person p2("Tom", 10);cout << myCompare(p1, p2) << endl;
}

学习模板并不是为了写模板,而是在STL中能够运用系统提供的模板

3、 类模板
3.1 类模板语法
类模板作用

建立一个通用类,类中成员数据类型可以不具体制定,用一个虚拟的类型代表
语法

template<typename T>
参数template:声明创建模板
typename:表明其后面的符号是一种数据类型,可以用class来代替
T:通用的数据类型,名称可以替换,通常为大写字母
template<typename NameT, typename AgeT>
class Person
{
public:Person(NameT name, AgeT age){m_Age = age;m_Name = name;}NameT m_Name;AgeT m_Age;
};
void test()
{Person<string, int>("Tom", 30);  // 调用-只有一种调用方式
}

3.2 类模板和函数模板的区别
类模板与函数模板区别主要有两点

类模板没有自动类型推导的使用方式

类模板在模板参数列表中可以有默认参数

template<typename NameT, typename AgeT = int>  // 默认参数
class Person
{
public:Person(NameT name, AgeT age){m_Age = age;m_Name = name;}NameT m_Name;AgeT m_Age;
};
void test()
{Person<string>("Tom", 30);
}

3.3 使用时机
类模板中成员函数和普通类中成员函数创建时机是有区别的

普通类中的成员函数一开始就可以创建
类模板中的成员函数在调用时才创建

class Person1
{
public:void show(){cout << "Person1" << endl;}};template<typename T>
class Person
{
public:// 没调用,其不会编译,因为无法确定T的数据类型T p1;void func1(){p1.show();}};
void test()
{Person<Person1> p;p.func1();
}

3.4 类模板对象函数做参数
类模板实例出的对象,向函数传参

一共有三种传入方式

指定传入的数据类型:直接显示对象的数据类型

// 类模板做函数的参数
template<class T1, class T2>
class Person
{
public:Person(T1 name, T2 age){m_Name = name;m_Age = age;}T1 m_Name;T2 m_Age;void showPerson(){cout << "name:" << m_Name << " age:" << m_Age << endl;}
};
// 指定传入类型
void printPerson1(Person<string, int> &p)  
{p.showPerson();
}
// 参数模板化
template<class T1, class T2>
void printPerson2(Person<T1, T2>& p)
{p.showPerson();cout << "T1的类型为:" << typeid(T1).name() << endl;cout << "T2的类型为:" << typeid(T2).name() << endl;
}
// 整个类模板化
template<class T>
void printPerson3(T &p)
{p.showPerson();
}
void test()
{Person<string, int> p("Tom", 12);printPerson1(p);printPerson2(p);printPerson3(p);
}

二、 STL 初识
1、 基本概念
STL 基本模板库
STL 从广义上分为容器、算法和迭代器
容器和算法事件通过迭代器无缝连接
STL 几乎所有的代码都采用了模板类或模板函数
2、 STL 六大组件
STL 大体分为六大组件:容器、算法、迭代器、仿函数、适配器(配接器)、空间配置器

容器:各种数据结构:vector、list、deque、set、map等,用来存放数据
算法:各种常用的算法,如sort、find、copy、for_each等
迭代器:扮演了容器和算法之间的胶合剂
仿函数:行为类似的函数,可作为算法的某种策略
适配器:一种用来修饰容器或者仿函数或迭代器接口的东西
空间配置器:负责空间的配置和管理
2.1 容器、算法、迭代器
容器:置物之所也

STL 容器就是将运用最广泛的一些数据结构实现出来

常用的数据结构:数组、列表、树、栈、队列、集合、映射表等

这些容器分为序列式容器和关联式容器两种

序列式容器:强调值的排序,序列式容器中的每个元素均有固定的位置
关联式容器:二叉树结构,各元素之间没有严格的物理上的顺序关系
算法:问题之解也

有限的步骤,解决逻辑或数学上的问题,这叫做算法

算法分为:质变算法和非质变算法

质变算法:是指运算过程中会更改区间内的元素的内容,例如拷贝、替换、删除等等
非质变算法:是指运算过程中不会更改区间内的元素内容,例如查找、计数、遍历、寻找极值等等
迭代器:容器和算法之间粘合剂

提供一种方法,使之能够依序寻访某个容器所含有的各个元素,而又无需暴露该容器的内部表示方式

每个容器都有自己专属的迭代器

迭代器使用非常类似于指针

迭代器种类
在这里插入图片描述
常用的容器中迭代器种类为双向迭代器和随机访问迭代器

3、 迭代器初始
3.1 vector 存放内置数据类型
容器:vector

算法:for_each

迭代器:vector::iterator

#include <vector>  // vector 头文件
#include <algorithm>  // 标准算法头文件void printVector(int value)
{cout << value << endl;
}
// vector 存放内置数据类型
void test()
{// 创建一个 vector 容器——数组vector<int> v;// 向容器中插入数据v.push_back(10);  // 尾插数据v.push_back(11);v.push_back(12);// 通过迭代器访问容器中的数据vector<int>::iterator itBegin = v.begin(); // 起始迭代器,指向容器中第一个元素,当做指针使用vector<int>::iterator itEnd = v.end();  // 结束迭代器,指向容器最后一个元素的下一个位置// 第一种遍历方式while (itBegin != itEnd){cout << *itBegin << endl;itBegin++;}// 第二种遍历方式for (vector<int>::iterator it = v.begin(); it != v.end(); it++){cout << *it << endl;}// 第三种遍历方式for_each(v.begin(), v.end(), printVector);  // 回调函数
}

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

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

相关文章

Ubuntu搭建Samba服务-学习记录

文章目录 Ubuntu安装Samba流程Samba配置文件Samba添加账户配置文件修改Samba服务控制设置开机自动启动通过systemctl 启动服务通过 rc.local 启动 Windows访问参考链接 当前文章仅用于记录&#xff0c;在 Ubuntu中安装使用Samba&#xff0c;在Windows访问 系统环境&#xff1a;…

NestJS 的 Module 学习

Module 概念 模块使用Module()装饰器来装饰的类。装饰器Module()提供 NestJS 用于组织应用程序结构相关的数据&#xff0c;例如提供商和控制器等等。具体的结构图如下&#xff1a; [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-T3CAmLIm-16902949…

【JS 同步调用多个函数 Promise.all】

在 JS 异步编程中&#xff0c;可以使用 Promise.all 方法来实现同步调用多个函数。 Promise.all 方法接收一个包含各个 Promise 对象的数组作为参数&#xff0c;返回一个新的 Promise 对象。当数组中所有的 Promise 对象都成功&#xff08;即状态为 resolved&#xff09;时&am…

【问题记录】Ubuntu 22.04 环境下,程序报:段错误(核心已转储)怎么使用 core 文件和GDB调试器 解决?

目录 环境 问题情况 解决思路 原因分析 解决方法 番外知识 环境 VMware Workstation 16 Pro &#xff08;版本&#xff1a;16.1.2 build-17966106&#xff09;ubuntu-22.04.2-desktop-amd64 问题情况 本人在运行百万并发的服务端程序时&#xff0c;程序运行报&#xff1a…

JVM运行时数据区——方法区的垃圾回收

方法区的垃圾回收主要是两部分&#xff1a;运行时常量池中废弃的常量和不在使用的类。 类卸载(将不在使用的类回收)的条件&#xff1a; 该类的所有实例均被回收。 加载该类的类加载器被回收(一般很难满足)。 类对象不再引用&#xff0c;通过反射也获取不到。

alias取别名后,另一个shell中和shell脚本中不生效的问题以及crontab执行docker失败问题

目录 问题一&#xff1a;用alias取别名后&#xff0c;另一个shell中不生效描述原因解决 问题二&#xff1a;用alias取别名后&#xff0c;别名在脚本中不生效描述原因解决 问题三&#xff1a;crontab计划任务不能运行docker命令描述原因解决 问题一&#xff1a;用alias取别名后&…

VLAN---虚拟局域网

VLAN— 虚拟局域网 LAN—局域网 MAN—城域网 WAN—广域网 1.一个VLAN相当于是一个广播域 VLAN—通过路由器和交换机协同工作后&#xff0c;将原本的一个广播域逻辑上&#xff0c;拆 分为多个虚拟的广播域。 VLAN配置&#xff1a; 1.创建VLAN VID—VLAN ID------用来区分和…

浅谈能源管理系统在水泥行业中设计分析

安科瑞 华楠 摘要&#xff1a;水泥企业作为我国产业结构中重要的耗能产业&#xff0c;同时对环境的污染也比较大&#xff0c;因此在水泥企业中建立能源管理系统&#xff0c;对水泥企业的生产过程过程进行全过程的监控和管理&#xff0c;对于降低企业的能源消耗和提高企业的经济…

【Ajax】笔记-Axios与函数发送AJAX请求

Axios 和 Ajax 的区别 1、Axios是一个基于Promise的HTTP库&#xff0c;而Ajax是对原生XHR的封装&#xff1b; 2、Ajax技术实现了局部数据的刷新&#xff0c;而Axios实现了对ajax的封装。 优缺点&#xff1a; ajax&#xff1a; 本身是针对MVC的编程,不符合现在前端MVVM的浪潮 基…

Rust中的Iterator和IntoIterator介绍及应用

Iterator即迭代器&#xff0c;它可以用于对数据结构进行迭代。被迭代的数据结构是可迭代的(iterable)&#xff0c;所谓的可迭代就是这个数据结构有返回迭代器的方法&#xff0c;由于Rust的所有权机制&#xff0c;对一个数据结构的迭代器&#xff0c;有三种&#xff1a; 拿走数…

【MySQL】之复合查询

【MySQL】之复合查询 基本查询多表查询笛卡尔积自连接子查询单行子查询多行子查询多列子查询在from子句中使用子查询 合并查询小练习 基本查询 查询工资高于500或岗位为MANAGER的雇员&#xff0c;同时还要满足他们的姓名首字母为大写的J按照部门号升序而雇员的工资降序排序使用…

性能测试Ⅱ(压力测试与负载测试详解)

协议 性能理论&#xff1a;并发编程 &#xff0c;系统调度&#xff0c;调度算法 监控 压力测试与负载测试的区别是什么&#xff1f; 负载测试 在被测系统上持续不断的增加压力&#xff0c;直到性能指标(响应时间等)超过预定指标或者某种资源(CPU&内存)使用已达到饱和状…

全志F1C200S嵌入式驱动开发(解决spi加载过慢的问题)

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】 之前的几个章节当中,我们陆续解决了spi-nor驱动的问题、uboot支持spi-nor的问题。按道理来说,下面要做的应该就是用uboot的loady命令把kernel、dtb、rootfs这些文件下载到ddr,然…

Mysql中日期时间的加减

Mysql中日期时间的加减&#xff0c;可以使用date_add()函数和date_sub()函数 1、date_add()为日期增加一个时间间隔 语法格式为: DATE_ADD(date,INTERVAL expr type) #date 指定的时间&#xff0c;可以是now()&#xff0c;也可以是其它时间 #INTERVAL 间隔关键字 #expr 添加…

WebRTC Simulcast介绍

原文地址&#x1f447; https://blog.livekit.io/an-introduction-to-webrtc-simulcast-6c5f1f6402eb/ 你想知道的关于Simulcast的一切 Simulcast是WebRTC中最酷的功能之一,它允许WebRTC会议在参与者网络连接不可预测的情况下进行扩展。在这篇文章中,我们将深入探讨Simulcas…

element ui input 深层循环v-model绑定默认数据删除不了的情况

例子&#xff1a; 在项目开发中遇到的&#xff0c;简单记录一下 <el-input style"width: 180px"v-model"item.dataForm"input"handleChangeDataForm($event)"type"number"placeholder"请输入1-2的数值"size"smal…

欧姆龙CX系列PLC串口转以太网欧姆龙cp1hplc以太网连接电脑

你是否还在为工厂设备信息采集困难而烦恼&#xff1f;捷米特JM-ETH-CX转以太网通讯处理器为你解决这个问题&#xff01; 捷米特JM-ETH-CX转以太网通讯处理器专门为满足工厂设备信息化需求而设计&#xff0c;可以用于欧姆龙多个系列PLC的太网数据采集&#xff0c;非常方便构建生…

【育儿】幼儿学习笔记 (一)

文章目录 [TOC] 一、前言二、2~6岁 目标三、1~3年级 目标学习内容校内校外 三、学习技巧表达结构表达方法板块化学习学习进度控制古诗词推荐 四、听文史类幼儿园小学 五、看 一、前言 语文、英语属于语言类学科 二、2~6岁 目标 听 ★★★★★ \color{Orange}{★★★★★} ★…

设计模式之责任链模式

// 定义请求类 class Request {private String content;public Request(String content) {this.content content;}public String getContent() {return content;} }// 抽象处理器 abstract class Handler {protected Handler successor; // 后继处理器public void setSuccesso…

Go语言channel

通道 通道&#xff08;channel&#xff09;是Go语言提供的一种在gorountine之间进行数据创术的通信机制。通道的声明非常简单&#xff0c;只需要使用chan 关键字即可&#xff0c;关闭则需要使用close函数。 注意&#xff1a;通过close函数关闭channel不是必须的。不主动关闭的…