C++学习笔记(三)

C++学习笔记(三)

1、模板

1.1 模板的概念

模板就是建立通用的模具,大大提高复用性

模板的特点:

  1. 模板不可以直接使用,它只是一个框架
  2. 模板的通用并不是万能的
1.2 函数模板
  • C++另一种编程思想称为泛型编程,主要利用的技术就是模板
  • C++提供两种模板机制:函数模板和类模板
1.2.1 函数模板语法

函数模板作用:建立一个通用函数,其函数返回值类型和形参类型可以不具体制定,用一个虚拟的类型来代表

这里是引用

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

在这里插入图片描述

两种方式使用函数模板

  • 自动类型推导

  • 显示指定类型
    在这里插入图片描述

1.2.2 函数模板注意事项
  • 自动类型推导,必须推导出一致的数据类型T,才可以使用
    在这里插入图片描述

  • 模板必须要确定出T的数据类型,才可以使用
    在这里插入图片描述

1.2.3 普通函数与函数模板的区别
  • 普通函数调用时可以发生自动类型转换(隐式类型转换)

  • 函数模板调用时,如果利用自动类型推导,不会发生隐式类型转换

  • 如果利用显示指定类型的方式,可以发生隐式类型转换

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

建议使用显示指定类型的方式,调用函数模板,因为可以自己确定通用类型T

1.2.4 普通函数与函数模板调用规则
  1. 如果函数模板和普通函数都可以调用,优先调用普通函数
    在这里插入图片描述

  2. 可以通过空模板参数列表强制调用函数模板
    在这里插入图片描述

  3. 函数模板可以发生函数重载
    在这里插入图片描述

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

在这里插入图片描述

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

1.2.5 模板的局限性

模板的通用性并不是万能的
例如,如果传入的两个数组类型的变量,无法进行赋值操作,又例如,传入自定义类型变量,无法进行比较运算

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

在这里插入图片描述
在这里插入图片描述

利用具体化的模板,可以解决自定义类型的通用化
学习模板并不是为了写模板,而是在STL能够运用系统提供的模板

1.3 类模板

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

语法:
在这里插入图片描述
template——声明创建模板
typename——表明其后面的符号是一种数据类型,可以用class代替
T ——通用的数据类型,名称可以替换,通常为大写字母

1.3.1 类模板基本语法


在这里插入图片描述

类模板和函数模板语法相似,在声明模板template后面加类,此类称为类模板

1.3.1 类模板与函数模板区别
  • 类模板没有自动类型推导的使用方式
    在这里插入图片描述

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

    在这里插入图片描述

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

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

1.3.3 类模板对象做函数参数

类模板实例化出的对象,向函数传参的方式:
1.指定传入类型——直接显示对象的数据类型 (最常用)
在这里插入图片描述

2.参数模板化——将对象中的参数变为模板进行传递
在这里插入图片描述

3.整个类模板化——将这个对象类型模板化进行传递
在这里插入图片描述

1.3.4 类模板与继承

当类模板碰到继承时,需要注意:

  • 当子类继承的父类是一个类模板时,子类在声明的时候,要指定出父类中T的类型
    在这里插入图片描述

  • 如果不指定,编译器无法给子类分配内存

  • 如果想灵活指定出父类中T的类型,子类也需变为类模板
    在这里插入图片描述

1.3.5 类模板成员函数类外实现

在这里插入图片描述
在这里插入图片描述

1.3.5 类模板分文件编写

问题:类模板中成员函数创建时机是在调用阶段,导致分文件编写时链接不到
解决:
1.直接包含.cpp源文件(少用)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.将声明和实现写到同一个文件中,并更改后缀名为.hpp,hpp是约定的名称,并不是强制(主流)

在这里插入图片描述
在这里插入图片描述

1.3.6 类模板与友元

类模板配合友元函数的类内和类外实现

  • 全局函数类内实现——直接在类内声明友元即可
  • 全局函数类外实现——需要提前让编译器知道全局函数的存在

在这里插入图片描述
在这里插入图片描述

建议全局函数做类内实现,用法简单,而且编译器可以直接识别

2、STL

  • 长久以来,软件界希望建立一种可重复利用的东西
  • C++的面向对象和泛型编程思想,目的就是复用性的提升
  • 为了建立数据结构和算法的一套标准,诞生了STL
2.1 STL基本概念
  • STL(Standard Template Library)标准模板库
  • STL从广义上分为:容器(container)、算法(algorithm)、迭代器(iterator)
  • 容器和算法之间通过迭代器进行无缝连接
  • STL几乎所有的代码都采用了模板类或者模板函数
2.2 STL六大组件
  • 容器:各种数据结构,如vector、list、deque、set、map等,用来存放数据
  • 算法:各种常用的算法,如sort、find、copy、for_each等
  • 迭代器:扮演了容器与算法之间的胶合剂
  • 仿函数:行为类似函数,可作为算法的某种策略
  • 适配器(配接器):一种用来修饰容器或者仿函数或迭代器接口的东西
  • 空间配置器:负责空间的配置与管理
2.3 STL中容器、算法、迭代器

在这里插入图片描述
每个容器都有自己专属的迭代器,迭代器使用非常类似于指针在这里插入图片描述
迭代器种类
在这里插入图片描述
常用的容器中迭代器种类为双向迭代器随机访问迭代器

2.4 STL初识
2.4.1 vector存放内置数据类型

容器:vector
算法:for_each
迭代器:vector< int >::iterator

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

2.4.2 vector存放自定义数据类型

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

要知道*it代表什么
如果是person,就是对象
如果是person *,就是指针

2.4.3 vector容器嵌套容器

在这里插入图片描述
在这里插入图片描述

2.5 STL常用容器
2.5.1 string容器
2.5.1.1 string基本概念

本质:string是C++风格的字符串,而string本质上是一个类

string和char*的区别:

  • char*是一个指针
  • string是一个类,类内部封装了char*,管理这个字符串,是一个char*型的容器

特点:
string类内部封装了很多成员方法
例如:查找find,拷贝copy,删除delete,替换replace,插入insert
string管理char*所分配的内存,不用担心复制越界和取值越界等,由类内部进行负责

2.5.1.2 string构造函数

在这里插入图片描述
在这里插入图片描述

2.5.1.3 string赋值操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

string的赋值方式很多,operator=这种方式是比较实用的

2.5.1.4 string字符串拼接

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

2.5.1.5 string查找和替换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

find查找是从左往后,rfind从右往左
find找到字符串后返回查找的第一个字符位置,找不到返回-1
replace在替换时,要指定从哪个位置起,多少个字符,替换成什么样的字符串

2.5.1.6 string字符串比较


在这里插入图片描述

2.5.1.7 string字符存取

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

string字符串中单个字符存取有两种方式,利用[ ]或at

2.5.1.8 string插入和删除

在这里插入图片描述
在这里插入图片描述

2.5.1.9 string子串

在这里插入图片描述
在这里插入图片描述

2.5.2 vector容器

功能:vector数据结构和数组非常相似,也称为单端数组

vector与普通数组区别:

不同之处在于数组是静态空间,而vector可以动态扩展

动态扩展并不是在原空间之后续接新空间,而是找更大的内存空间,然后将原数据拷贝新空间,释放原空间
在这里插入图片描述
vector容器的迭代器是支持随机访问的迭代器

2.5.2.1 vector构造函数

在这里插入图片描述
在这里插入图片描述在这里插入图片描述

2.5.2.2 vector赋值操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

vector赋值方式比较简单,使用operator=,

2.5.2.3 vector容量和大小

在这里插入图片描述
在这里插入图片描述

2.5.2.4 vector插入和删除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.2.5 vector数据存取

在这里插入图片描述
在这里插入图片描述

2.5.2.6 vector互换容器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

swap可以使两个容器互换,可以达到实用的收缩内存效果

2.5.2.7 vector预留空间

在这里插入图片描述
在这里插入图片描述

2.5.3 deque容器
2.5.3.1 deque容器基本概念

双端数组,可以对头端进行插入删除操作

在这里插入图片描述
在这里插入图片描述
deque内部工作原理:

deque内部有个中控器,维护每段缓冲区中的内容,缓冲区中存放真实数据
中控器维护的是每个缓冲区发地址,使得使用deque时像一片连续的内存空间

在这里插入图片描述

2.5.3.2 deque容器构造函数

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.3.3 deque赋值操作

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.3.4 deque大小操作


在这里插入图片描述

  • deque没有容量的概念
2.5.3.5 deque插入和删除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

插入和删除提供的位置是迭代器

2.5.3.6 deque数据存取

在这里插入图片描述
在这里插入图片描述

2.5.3.7 deque排序

在这里插入图片描述
在这里插入图片描述

2.5.4 stack容器
2.5.4.1 stack基本概念

stack是一种先进后出的数据结构,它只有一个出口

外界只能访问栈顶的元素,因此栈不允许有遍历行为
栈可以判断容器是否为空
栈可以返回元素个数

在这里插入图片描述

  • 入栈:栈中进入数据
  • 出栈:栈中弹出数据
2.5.4.2 stack常用接口

在这里插入图片描述

2.5.5 queue容器
2.5.5.1 queue基本概念

queue是一种先进先出的数据结构,它有两个出口

在这里插入图片描述

  • 队列容器允许从一端新增元素,从另一端移除元素
  • 队列中只有队头和队尾才可以被外界使用,因此队列不允许有遍历行为

入队:队列中进数据
出队:队列中出数据

在这里插入图片描述

2.5.5.2 queue常用接口

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.6 list容器
2.5.6.1 list基本概念

功能:将数据进行链式存储
链表是一种物理存储单元上非连续的存储结构,数据结构的逻辑顺序是通过链表中的指针链接实现的

  • 链表的组成:链表是由一系列结点组成
  • 结点的组成:一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域
  • STL中的链表是一个双向循环链表

在这里插入图片描述
由于链表的存储方式并不是连续的内存空间,因此链表list中的迭代器只支持前移和后移,属于双向迭代器

list的优点:

  • 采用动态存储分配,不会造成内存浪费和溢出
  • 链表执行插入和删除操作十分方便,修改指针即可,不需要移动大量元素

list的缺点:

  • 链表灵活,但是空间和时间额外耗费较大

list有一个重要的性质,插入操作和删除操作都不会造成原有list迭代器的失效,这在vector是不成立的

STL中list和vector是两个最常被使用的容器,各有优缺点

2.5.6.2 list构造函数

在这里插入图片描述
在这里插入图片描述

list构造方式同其他几个STL常用容器,熟练掌握即可

2.5.6.3 list容器赋值与交换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.6.4 list大小操作

在这里插入图片描述
在这里插入图片描述

2.5.6.5 list插入和删除

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.6.6 list数据存取

在这里插入图片描述
不可以用[ ]形式或者at访问list容器中的元素,原因是list本质是链表,不是用连续线性空间存储数据,迭代器也是不支持随机访问的(不能跳跃式访问)
在这里插入图片描述

2.5.6.7 list反转和排序

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

  • 对于自定义数据类型,必须要指定排序规则,否则编译器不知道如何进行排序
  • 高级排序只是在排序规则上再进行一次逻辑规则制定,并不复杂
2.5.7 set容器
2.5.7.1 set容器基本概念

所有元素都会在插入时自动被排序

本质:set/multiset属于关联式容器,底层结构是用二叉树实现

set和multiset区别:

  • set不允许容器中有重复的元素
  • multiset允许容器中有重复的元素
2.5.7.2 set构造及赋值

在这里插入图片描述
在这里插入图片描述

  • set容器插入数据时用insert
  • set容器插入数据的数据会自动排序
2.5.7.3 set大小和交换

在这里插入图片描述

2.5.7.4 set插入和删除

在这里插入图片描述

在这里插入图片描述

2.5.7.5 set查找和统计

在这里插入图片描述

在这里插入图片描述

  • find——返回的是迭代器
  • count——对于set结果为0或者1
2.5.7.6 set和multiset区别

区别:

  • set不可以插入重复数据,而multiset可以
  • set插入数据的同时会返回插入结果,表示插入是否成功
  • multiset不会检测数据,因此可以插入重复数据
2.5.7.7 pair对组创建

成对出现的数据,利用对组可以返回两个数据

在这里插入图片描述
在这里插入图片描述

2.5.7.8 set容器排序

利用仿函数,可以改变排序规则

1.set存放内置数据类型
在这里插入图片描述
在这里插入图片描述在这里插入图片描述
利用仿函数指定排序规则

2.set存放自定义数据类型

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

对于自定义数据类型,set必须要指定排序规则才可以插入数据

2.5.8 map容器
2.5.8.1 map容器基本概念
  • map中所有元素都是pair
  • pair中第一个元素为key(键值),起到索引作用,第二个元素为value(实值)
  • 所有元素都会根据元素的键值自动排序

本质:
map/multimap属于关联式容器,底层结构是用二叉树实现
优点:

  • 可以根据key值快速找到value值
    map和multimap区别:

  • map不允许容器中有重复key值元素

  • multimap允许容器中有重复key值元素

2.5.8.2 map构造和赋值

在这里插入图片描述
在这里插入图片描述

map中所有元素都是成对出现,插入数据时候要使用对组

2.5.8.3 map大小和交换

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.8.4 map插入和删除

在这里插入图片描述
在这里插入图片描述

2.5.8.5 map查找和统计

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

2.5.8.6 map容器排序
  • 利用仿函数,可以改变排序规则

在这里插入图片描述
在这里插入图片描述

2.5.9 容器比较

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值