C++候捷stl-视频笔记1

认识headers、版本、重要资源

STL的核心思想是泛型编程

新式头文件内的组件封装在命名空间std中:
using namespace std;
using std::cout;或std::vector vec;
旧式头文件内的组件不封装在命名空间std中

注:不建直接使用using namespace xxx,如果使用的头文件有被外部文件引用,有命名冲突的风险。建议打开具体的使用对象,如using std::cout;,或者使用时打开std::string a;
http://www.cplusplus.com/
https://en.cppreference.com/w/
http://gcc.gnu.org/

STL体系结构基础介绍

STL六大部件::
容器:放数据的模版类,帮我们解决掉内存的问题
分配器:是来支持容器将数据放到内存里
算法:是一个个函数来处理存放在容器里的数据,一种模版函数(模版编程,与oop不同,操作数据的函数与数据不在一起)
迭代器:一套访问容器的接口,类似泛化的指针
仿函数:作用类似函数,例如相加相减等等
适配器:有三种,分别将容器,迭代器,仿函数来进行一个转换
在这里插入图片描述
在这里插入图片描述
allocator 是分配器(一般忽略),vector 是容器,count_if 是算法
vi.begin() 是迭代器
not1,bind2nd是适配器
less 是仿函数

判断条件 predicate 为:not1(bind2nd(less(), 40)) —— 表示 >= 40 数为真(小于40的否定)

容器为前闭后开区间
在这里插入图片描述

容器之分类与各种测试

序列式容器:按照元素的存储顺序依次排列
Array:容量大小固定
Vector:单端进出,容量大小可动态扩展
Deque:双端可进可出
List:双向循环链表,不连续
Forward-List:内存占用少于双向链表
关联式容器:包括键和值,适合快速查找
集合(Set/Multiset):由红黑树(高度平衡二叉树)实现,key就是value,value就是key。mult元素可重复
映射表(Map/Multimap):由红黑树(高度平衡二叉树)实现。mult键值可重复
不定序容器:底层使用哈希表实现。
无序集合(Unordered Set/Multiset):由哈希表实现
无序映射表(Unordered Map/Multimap):由哈希表实现
哈希表包括若干个bucket,每个bucket对应一个链表。哈希冲突时,应避免每个bucket对应的链表长度过长而导致元素搜索时间较长
在这里插入图片描述
Array50万个元素,随机填充容器47ms, 0-32767查找20000,排序和搜索187ms(二分查找前需排序)
vector:push_back100万个元素。每次push_back申请的空间以两倍增长,会申请预留空间。size是大小,capacity是申请的内存空间大小;是另外找一个两倍大的空间。可能出现申请内存空间不足,需要try,catch抓取异常。 随机数据填充容器:3063ms;直接搜索,次序查找:0ms(搜索时间看运气,运气很好);排序后二分查找:2765ms。
listpush_back100万个元素。随机数据填充容器:3265ms;直接搜索:16ms;排序:2312ms。 c.sort(); 是容器自带的排序函数,如果容器自带肯定是要比全局的排序函数好的
forward_list:forward_list 只有 c.push_front(); 且没有 forward_list.back() forward_list.size()。100万个元素。随机数据填充容器:3204ms;直接搜索:15ms;排序:2656ms
deque:类似vector,两边都能扩充,实际上是分段连续的。其是通过 map(是一个vector,但在扩充时会 copy 到中间)里的指针指向各个 buffer,buffer 里再存数据,每个 buffer 的大小一致,每次扩充都是扩充一个指针指向一个新的 buffer。随机数据填充容器:2704ms;直接搜索:15ms;排序:3110ms
(关联性容器查找都非常快)
栈stack和队列queue底层依赖于deque容器,由于其没有自己的数据结构,因此不把stack和queue作为容器,而作为容器适配器;
在这里插入图片描述
在这里插入图片描述
multiset:有自己提供用于查找的find()函数时,效率更高。insert自动排序,底层结构是红黑树。随机数据填充容器:6609ms(其在填充的时候就进行排序了);直接搜索 ::find():203ms;c.find():0ms
multimap:multimap.inset(pair<int,string>),要自己组合pair<int,string>元素放进去。随机数据填充容器:4812ms(其在填充的时候就进行排序了);c.find():0m
unordered_multiset:bucker_count()篮子数量,篮子一定比元素多,每个篮子的链表不能太长(经验法则:当元素个数大于等于bucket个数时,bucket个数会扩充至约原先的2倍。)。bucket_size()可以看篮子里有多少数量。随机数据填充容器:4406ms;直接搜索 ::find():109ms;c.find():0ms;前二十个 bucket 中只有一个有24个元素
unordered_multimap与unordered_multiset类似
set:key就是value,value就是key,插入重复的值,不会增长元素
map:[]会自动合成Pair格式

分配器之测试

容器需要分配器allocator作为支撑;每个容器类都有默认的容器分配器allocator(模板参数使用默认值)。

template<typename _Tp, typename _Alloc = std::allocator<_Tp>>	// 使用默认参数
class vector : protected _Vector_base<_Tp, _Alloc>template<typename _Tp, typename _Alloc = std::allocator<_Tp>>	// 使用默认参数
class list : protected _List_base<_Tp, _Alloc>template<typename _Tp, typename _Alloc = std::allocator<_Tp>>	// 使用默认参数
class deque : protected _Deque_base<_Tp, _Alloc>template<typename _Key, typename _Compare = std::less<_Key>,typename _Alloc = std::allocator<_Key>>
class set ...template<typename _Key, typename _Tp, typename _Compare = std::less<_Key>,typename _Alloc = std::allocator<std::pair<_Key, _Tp>>
class map ...template<class _Value, class _Hash = hash<_Value>, class _Pred = std::equal_to<_Value>, class _Alloc = std::allocator<_Value>>
class unordered_set ...template<class _Key, class _Tp, class _Hash = hash<_Key>, class _Pred = std::equal_to<_Key>,class _Alloc = std::allocator<std::pair<_Key, _Tp>>
class unordered_map ...

在这里插入图片描述
不建议手动使用分配器直接管理内存 allocate()和deallocate()函数释放内存时需释放指针和对应大小的内存。

面向对象编程(OOP) vs. 泛型编程(GP)

OOP=数据+操作,OOP是想要把data和method关联在一起打包

// list容器的迭代器不支持随机访问
template <class T, class Alloc = alloc>
class list {...void sort();	// list容器类的成员函数sort()
};

标准库中很少有继承关系,因此虚函数很少,关系比较简单

GP是将data和methods分开来
容器类

// vector容器的迭代器支持随机访问
template <class T, class Alloc = alloc>
class vector {...
};// deque容器的迭代器支持随机访问
template <class T, class Alloc = alloc, size_t BufSiz = 0>
class deque {...
};

Alogorithm是全局函数

/* STL标准库提供的全局::sort() */
// ::sort(c.begin(), c.end())
template <class RandomAccessIterator>	// 随机访问迭代器
inline void sort(RandomAccessIterator first, RandomAccessIterator last) {...
}template <class RandomAccessIterator, class Compare> // 比较规则
inline void sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp) {...
}

Containers和Alogorithm可以各自闭门造车,然后以iterator联通既可
Alogorithm通过Iterator确定操作范围,并通过Iterators取用Continer元素;

/* max函数的重载 */
template <class T>
inline const T& max(const T& a, const T& b) {return a < b ? b : a;
}// Compare 自定义的比较规则
template <class T, class Compare>
inline const T& max(const T& a, const T& b, Compare comp) {return comp(a, b) ? b : a;
}

在标准库中操作符重载变得至关重要

为什么list不能使用::sort()排序?
List的迭代器不能跳来跳去,不能随机访问,只能一个一个往前跳,不能直接+5,-5;标准库sort()所用到的随机访问迭代器,而list迭代器不足以达到要求;
在这里插入图片描述

所有Algorithms,其内最终设计元素本身的操作,无非就是比大小

技术基础:操作符重载and模板(泛化,全特化,偏特化)

操作符重载示例
在这里插入图片描述
类模版
调用者在使用时再指定泛型的具体类型。

template<typename T>	// 类模板
class complex{
private:T re, im;	// 模板friend complex& __doap1 (complex *ths, const complex& r); 	// 友元函数
public:complex(T r = 0, T i = 0) : re(r), im(i){}	// 默认参数、初始化列表complex& operate+=(const complex&);	// 重载运算符T real() const { return re; }		// 成员函数-常函数T imag() const { return im; }
};

类模板使用时,需显式指定具体的泛型类型。编译器不会对类模板进行类型推导

{complex<double> c1(1.1, 2.2);complex<int> c2(3, 4);
}

函数模版
class可替换为typename。
函数模板使用时,不必显式指定具体的泛型类型。编译器会对函数模板进行实参推导/类型推导(argument deduction)。类模板使用时,需显式指定具体的泛型类型。

// 函数模板
template<class T>
inline const T& min(const T& a, const T& b){return b < a ? b : a;
}
class stone{
public:stone(int w, int h, int we) : _w(w), _h(h), _weight(we){}bool operator< (const stone& rhs){return this->_weight < rhs._weight;}
private:int _w, _h, _weight;
}
int main(){stone r1(2, 3), r2(3, 3), r3;r3 = min(r1, r2);	
}

成员模版
类模板中的成员(函数/属性)也为模板
STL中的拷贝构造函数和有参构造函数常设计为成员模板
成员模板的泛型类型是类模板的泛型类型的子类。成员模板的泛型类型U1/U2,继承自类模板的泛型类型T1/T2。反之不成立。

class Base1 {};
class Derived1 : public Base1 {};
class Base2 {};
class Derived2 : public Base2 {};pair</* U1 */Devired1, /* U2 */Devired2> p;
pair<Base1, Base2> p2(p);
/* 等价写法 */
// 使用成员模板创建匿名对象,用于类的拷贝构造函数
pair</*T1*/Base1, /*T2*/Base2> p2(pair</*U1*/Devired1, /*U2*/Devired2>());

如智能指针子类shared_ptr有参构造函数的参数(被包装的指针),是智能指针父类__shared_ptr有参函数构造函数的参数(被包装的指针)的子类。

template<typename _Tp>
class shared_ptr : public __shared_ptr<_Tp>
{.../* 成员模板 */template<typename _Tp1>// 构造函数// 子类构造函数shared_ptr的参数__p,对父类构造函数__shared_ptr<_Tp>赋值explicit shared_ptr(/*Devired*/_Tp1* __p) : __shared_ptr</*Base*/_Tp>(__p) {}...
};/* 指针类的多态 */
Base1 *ptr = new Devired1;	// 向上转型up-cast
/* 智能指针类的多态 */
// 使用子类对象
shared_ptr<Base1*> sptr(new Devired1);	// 模拟向上转型up-cast

特化 specialization
泛化(generalization):使用时再指定模板参数的具体类型。
特化(specialization):将模板泛化的部分进行局部的特征化。显式指定部分或全部模板参数的具体类型
在这里插入图片描述
在这里插入图片描述
特化的优先级高于泛化。当存在合适的特化版本时,编译器优先调用相应的特化版本。
全特化的所有模板参数均被指定,故模板参数列表为空,即template <>。

全特化(full specialization):显式指定全部模板参数的具体类型。
偏特化/局部特化(partial specialization):指定部分模板参数的具体类型。

偏特化示例:两个模板参数,锁定其中一个
在这里插入图片描述
锁定范围的偏特化,如T是一个指针在这里插入图片描述

分配器

所有分配动作最终都会到malloc()函数
在这里插入图片描述
内存分配,蓝色是块是实际我们需要malloc给我们分配的空间,灰色的块是debug mode需要添加的内存空间,上下两个红色的块是cookie,它记录分配内存的大小(《深度探索c++对象模型》书上称为记录元素的大小,这个指的是delete时,该delete多大的内存空间,即delete掉的数组维度大小),绿色的部分指的是为了内存大小的对齐
vc6默认分配器allocators
在这里插入图片描述
VC6+的allocator只是以::operator new和::operator delete完成allocate()和deallocate(),没有任何特殊的设计
BC5编译器对于allocator分配内存和回收内存用的还是operator new和operator delete,底部还是用c语言的malloc和free完成,和VC6的实现一样

容器分配大量小的元素时,由于元素内存分配都用malloc,元素内存都很小,但额外开销很大。通常容器的元素都是较小的,因此额外开销比例较大,是不好接受的。

都是对malloc和free的各种包装,比起直接调用反而变慢了
在这里插入图片描述
GNU C++(G++) 2.9版本所附的标准库,allocator分配内存和回收内存用的还是operator new和operator delete,底部还是用c语言的malloc和free实现。但是自己的容器不用这个allcators,右下角说明这个分配器并没有被SGI STL header引入,即没有被使用
在这里插入图片描述
在这里插入图片描述
GC使用的是alloc分配器,核心诉求是尽量减少malloc的次数
共有16条链表,每一条链表负责特定大小的区块,编号为#0的链表负责大小为8B的内存块,编号为#1的链表负责大小为8 x 2 = 16B的内存块,编号为#3的链表负责大小为8 x 3 = 24B的内存块,…,以此类推,每次增加8B。每一条链表都是一次用malloc分配的一大块内存(带cookie),然后切分成小的标准块(不带cookie),当容器需要内存的时候,alloc就会按照需要的大小(变成8B的倍数)在链表中查找进行分配,这样实现在分配小块的时候就不需要存储cookie的开销了

G++4.9又不再使用alloc分配器,而是继续调用operator new 和operator delete
在这里插入图片描述
G++4.9的__pool_alloc就是G++2.9版本的alloc分配器
用例

vector<string, __gnu_cxx::__pool_alloc<string>> vec;// __gnu_cxx是一个命名空间

容器之间的实现关系与分类

在这里插入图片描述

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

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

相关文章

Meterpreter工具使用

Meterpreter属于stage payload&#xff0c;在Metasploit Framework中&#xff0c;Meterpreter是一种后渗透工具&#xff0c;它 属于一种在运行过程中可通过网络进行功能扩展的动态可扩展型Payload。这种工具是基于“内存DLL注 入”理念实现的&#xff0c;它能够通过创建一个新进…

SAP_MM_业务数据

在SAP的物料管理模块&#xff08;MM&#xff0c;Materials Management&#xff09;中&#xff0c;业务数据&#xff08;Transactional Data&#xff09;是日常业务操作所产生的动态数据。这些数据记录了与采购、库存和物料需求计划&#xff08;MRP&#xff09;相关的实际业务活…

微乐校园管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;叫车管理&#xff0c;代跑管理&#xff0c;二手商品管理 司机账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;叫车管理&#xff0c…

MPE中environment.py复盘

1.__init__ 初始化函数参数&#xff1a; world: 一个包含环境信息和所有智能体的世界对象。reset_callback, reward_callback, observation_callback, info_callback, done_callback: 这些都是回调函数&#xff0c;用于在环境的特定事件发生时执行相应的操作。shared_viewer: 一…

邦芒面试:面试官“青睐”你的微妙信号

在激烈的面试过程中&#xff0c;你是否好奇过面试官是如何评估你的表现&#xff0c;以及哪些举动表明你有可能成为他们心仪的候选人&#xff1f;接下来&#xff0c;我们将揭示面试官“青睐”你的几个微妙信号。 1. 主动分享职位详情 当面试官不仅满足于询问你的工作经历&#…

【Linux进程篇】Linux内核——程序地址空间的初构

W...Y的主页 &#x1f60a; 代码仓库分享&#x1f495; 程序地址空间回顾 我们在讲C语言的时候&#xff0c;大家应该都见过这样的空间布局图&#xff1a; 为了更好的验证不同的数据在内存中的存储位置&#xff0c;下面这段代码我们可以去实验一下&#xff1a; #include<…

云WAF:守护网络安全的强大盾牌

随着互联网技术的飞速发展&#xff0c;网络安全问题已经成为全球性的难题。为了应对日益复杂的网络安全威胁&#xff0c;云WAF&#xff08;Web Application Firewall&#xff0c;即Web应用防火墙&#xff09;应运而生&#xff0c;并以其强大的功能和优势&#xff0c;成为网络安…

GPT-4o:人工智能交互的新纪元

GPT-4o作为OpenAI最新发布的模型&#xff0c;标志着人工智能领域的一大飞跃&#xff0c;特别是在自然语言处理和交互体验上。本文将概述GPT-4o的主要特点、技术改进以及它如何改变我们与AI互动的方式。 GPT-4o的诞生背景 在GPT-4o之前&#xff0c;用户通过Voice Mode与ChatGPT…

Spring如何管理Bean的生命周期呢?

我们都知道&#xff0c;在面试的过程中&#xff0c;关于 Spring 的面试题&#xff0c;那是各种各样&#xff0c;很多时候就会问到关于 Spring的相关问题&#xff0c;比如 AOP &#xff0c;IOC 等等&#xff0c;还有就是关于 Spring 是如何管理 Bean 的生命周期的相关问题&#…

基于高光谱数据集的创新点实现-高斯核函数卷积神经网络

一、高光谱数据集简介 1.1 数据集简介 数据集链接在这:高光谱数据集(.mat.csv)-科研学术 数据集包含下面三个文件&#xff1a; 文件中包含.mat与.csv,145x145x220, 其实主要使用avirissub.csv文件&#xff0c;在代码上只是将mat文件转成了csv文件。具体avirissub.csv如下&am…

计算机网络-BGP基础概念

一、BGP的基本概念 BGP是一种实现自治系统AS之间的路由可达&#xff0c;并选择最佳路由的矢量性协议。早期发布的三个版本分别是BGP-1&#xff08;RFC1105&#xff09;、BGP-2&#xff08;RFC1163&#xff09;和BGP-3&#xff08;RFC1267&#xff09;&#xff0c;1994年开始使用…

企业微信群发群消息:策略、技巧与效果优化

在数字化营销日益盛行的今天&#xff0c;企业微信已成为企业与客户、员工之间沟通的重要桥梁。其中&#xff0c;群发群消息功能更是企业快速传递信息、提升沟通效率的关键工具。本文将深入探讨企业微信群发群消息的策略、技巧以及效果优化方法。 一、企业微信群发群消息的重要…

TiDB-从0到1-MVCC

TiDB从0到1系列 TiDB-从0到1-体系结构TiDB-从0到1-分布式存储TiDB-从0到1-分布式事务TiDB-从0到1-MVCC 一、MVCC Multi-Version Concurrency Control 多版本并发控制&#xff0c;其主要解决了读并发的问题。 其维持一个数据的多个版本使读写操作没有冲突。也就是说数据元素X…

oracle linux7安装oracle11g0204

1、平时需要修改 /etc/redhat-release文件为Red Hat Enterprise Linux 7,这次不需要了。 2、关闭selinx nano /etc/selinux/config 改为disabled 3、nano /etc/hosts 修改解析 在oracle服务器中增加 /etc/hosts中一个对应 192.168.1.10 CLOUD-MC-SQL1 4、修改系统文件 /…

虚拟机报错:VMX 进程已提前退出。VMware Workstation 无法连接到虚拟机。

解决报错&#xff1a;VMware Workstation 无法连接到虚拟机。请确保您有权运行该程序、访问该程序使用的所有目录以及访问所有临时文件目录。 VMX 进程已提前退出。 解决方案&#xff1a;右键桌面图标进入VMware Workstation Pro的属性设置&#xff0c;兼容性–勾选“以管理员…

【windows】Total Uninstall:一款功能强大的完全卸载软件

软件介绍 Total Uninstall是一款专业的软件卸载工具&#xff0c;旨在帮助用户彻底地清除计算机上的应用程序&#xff0c;包括与应用程序相关的所有文件和注册表项。以下是Total Uninstall的一些主要功能和特点&#xff1a; 完全卸载&#xff1a;软件可以监视应用程序的安装过程…

【C++题解】1321. 时钟旋转(2)

问题&#xff1a;1321. 时钟旋转&#xff08;2&#xff09; 类型&#xff1a;字符串 题目描述&#xff1a; 时钟从时间&#xff1a;xx:xx&#xff08;xx时xx分&#xff09;&#xff0c;走到时间&#xff1a;xx:xx&#xff08;xx时xx分&#xff09;&#xff0c;时针共旋转了多…

uniapp一些问题解决

1.按钮边框如何去除&#xff1f; 参考博主&#xff1a;微信小程序按钮去不掉边框_微信小程序button去掉边框-CSDN博客文章浏览阅读1k次。最近在学uni-app&#xff0c;顺便自己写个小程序。左上角放了个button&#xff0c;可边框怎么也去不掉…原来微信小程序的按钮要去掉边框要…

新零售数据中台:打造智能商业运营的核心引擎_光点科技

随着数字化转型的浪潮席卷全球&#xff0c;新零售行业正在经历一场前所未有的革新。在这一过程中&#xff0c;“新零售数据中台”逐渐成为企业构建智能商业运营的核心引擎。本文将重点介绍新零售数据中台的概念、其在新零售中的作用&#xff0c;以及如何通过数据中台实现商业价…

npm yarn 更换国内源以及node历史版本下载地址【超简洁步骤】

npm 更换国内源 npm config set registryhttps://registry.npmmirror.com npm config set electron_mirrorhttps://registry.npmmirror.com/electron/yarn 更换国内源 yarn config set registry https://registry.npmmirror.comnode历史版本下载地址 https://nodejs.org/dow…