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

news2024/11/25 10:09:47

认识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.coloradmin.cn/o/1685696.html

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

相关文章

文章解读与仿真程序复现思路——电力系统保护与控制EI\CSCD\北大核心《基于改进Q学习算法和组合模型的超短期电力负荷预测》

本专栏栏目提供文章与程序复现思路&#xff0c;具体已有的论文与论文源程序可翻阅本博主免费的专栏栏目《论文与完整程序》 论文与完整源程序_电网论文源程序的博客-CSDN博客https://blog.csdn.net/liang674027206/category_12531414.html 电网论文源程序-CSDN博客电网论文源…

Llama 3 CPU推理优化指南

备受期待的 Meta 第三代 Llama 现已发布&#xff0c;我想确保你知道如何以最佳方式部署这种最先进的 (SoTA) LLM。在本教程中&#xff0c;我们将重点介绍如何执行仅权重量化 (WOQ) 来压缩 8B 参数模型并改善推理延迟&#xff0c;但首先&#xff0c;让我们讨论一下 Meta Llama 3…

贴片反射式红外光电传感器ITR8307

红外光电传感器ITR8307 ITR8307外形 特性 快速响应时间 高灵敏度 非可见波长 薄 紧凑型 无铅 该产品本身将保持在符合RoHS的版本内 描述 ITR8307/S18/TR8是一种光反射开关&#xff0c;它包括一个GaAs IR-LED发射器和一个NPN光电晶体管&#xff0c;该晶体管具有短距离的高…

基于 Milvus Cloud + LlamaIndex 实现初级 RAG

初级 RAG 初级 RAG 的定义 初级 RAG 研究范式代表了最早的方法论,在 ChatGPT 广泛采用后不久就取得了重要地位。初级 RAG 遵循传统的流程,包括索引创建(Indexing)、检索(Retrieval)和生成(Generation),常常被描绘成一个“检索—读取”框架,其工作流包括三个关键步…

C++实现图的存储和遍历

前言 许多新手友友在初学算法和数据结构时&#xff0c;会被图论支配过。我这里整理了一下图论常见的存储和遍历方式&#xff0c;仅供参考。如有问题&#xff0c;欢迎大佬们批评指正。 存储我将提到四种方式&#xff1a;邻接矩阵、vector实现邻接表、数组模拟单链表实现的前向星…

FFmpeg开发笔记(三十)解析H.264码流中的SPS帧和PPS帧

《FFmpeg开发实战&#xff1a;从零基础到短视频上线》一书的“2.1.1 音视频编码的发展历程”介绍了H.26x系列的视频编码标准&#xff0c;其中H.264至今仍在广泛使用&#xff0c;无论视频文件还是网络直播&#xff0c;H.264标准都占据着可观的市场份额。 之所以H.264取得了巨大…

完美解决原生小程序点击地图markers上的点获取不到对应的坐标信息

需求&#xff1a;地图上有多个markes点&#xff0c;点击每一个获取对应的数据&#xff0c;再根据当前的坐标信息去调用导航。 出现的问题&#xff1a;每次点击的时候获取不到对应的坐标信息&#xff0c;获取到的信息显然不是想要的 原因&#xff1a; 因为你的id不是number类型&…

线上虚拟纪念馆的便利与优势,全天候开放的数字化历史体验

一、搭建线上虚拟纪念馆的意义 在现代社会中&#xff0c;线上虚拟纪念馆越来越受到人们的关注和欢迎。传统纪念馆需要大量的物理空间和资源&#xff0c;而线上虚拟纪念馆则突破了这些限制&#xff0c;提供了更多的可能性和优势。首先&#xff0c;线上虚拟纪念馆能够更好地保存和…

【有手就行】使用你自己的声音做语音合成,CPU都能跑,亲测有效

此文介绍在百度飞桨上一个公开的案例&#xff0c;亲测有效。 厌倦了前篇一律的TTS音色了吗&#xff1f;打开短视频听来听去就是那几个声音&#xff0c;快来试试使用你自己的声音来做语音合成吧&#xff01;本教程非常简单&#xff0c;只需要你能够上传自己的音频数据就可以(建议…

Mac虚拟机工具 CrossOver 24.0.0 Beta3 Mac中文版

CrossOver是一款在Mac上运行Windows应用程序的软件&#xff0c;无需安装虚拟机或重启计算机&#xff0c;简化了操作过程&#xff0c;提高了工作效率&#xff0c;为用户带来便捷体验。前往Mac青桔下载&#xff0c;享受前所未有的便利和高效。摘要由作者通过智能技术生成 CrossOv…

JVM严镇涛版笔记【B站面试题】

前言 2023-06-19 18:49:33 出自B站 灰灰的Java面试 枫叶云链接&#xff1a;http://cloud.fynote.com/s/4976 JVM面试题大全 Lecturer &#xff1a;严镇涛 1.为什么需要JVM&#xff0c;不要JVM可以吗&#xff1f; 1.JVM可以帮助我们屏蔽底层的操作系统 一次编译&#xff0c…

当代人工智能三教父——深度学习三巨头

文章目录 引言 人物介绍 突出贡献 专业名词解释 引言 今天下午闲来无事翻阅了一下csdn首页的头条文章——《27 岁天才创始人 Joel Hellermark 分享了自己和“AI 教父” Geoffery Hinton 的最新采访》 感觉挺有意思&#xff0c;就从头到尾的看了一遍&#xff0c;里面有很多…

6.1 if语句

计算机语言和人类语言类似&#xff0c;人类语言是为了解决人与人之间交流的问题&#xff0c;而计算机语言是为了解决程序员与计算机之间交流的问题。程序员编写的程序就是计算机的控制指令&#xff0c;控制计算机的运行。借助于编译工具&#xff0c;可以将各种不同的编程语言的…

免费分享一套微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端+Vue管理端)【论文+源码+SQL脚本】,帅呆了~~

大家好&#xff0c;我是java1234_小锋老师&#xff0c;看到一个不错的微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端)【论文源码SQL脚本】&#xff0c;分享下哈。 项目视频演示 【免费】微信小程序旅游推荐(智慧旅游)系统(SpringBoot后端Vue管理端) Java毕业设计…

谷歌B端独立站建站推广,外贸建站训练营,傻瓜式教学

做外贸方法重要&#xff0c;工具更重要&#xff0c;而这些背后的规则和套路&#xff0c;身边的人往往不会告诉你&#xff0c;成功的人更不会教给你。本套课程主要内容包括&#xff1a;一套体系化的独立站建站方法&#xff0c;学会“高效学习”避免无效努力&#xff0c;拥有独立…

144.栈和队列:有效的括号(力扣)

题目描述 代码解决 class Solution { public:bool isValid(string s) {// 如果字符串长度为奇数&#xff0c;不可能是有效的括号字符串if(s.size() % 2 ! 0) return false;// 使用栈来存放括号stack<char> st;// 遍历字符串中的每一个字符for(int i 0; i < s.size();…

redis小知识

AOF与RDB的区别 AOF (Append Only File) 和 RDB (Redis Database) 都是Redis中的持久化机制&#xff0c;但有以下几点不同之处&#xff1a; 内容格式&#xff1a;AOF 以日志的形式记录所有写操作命令&#xff0c;而 RDB 则是在指定的时间间隔内对数据库进行快照&#xff0c;将数…

柏拉图式表征:人工智能深度网络模型是否趋于一致?

人工智能模型是否正在向现实的统一表征演进&#xff1f;柏拉图表征假说认为&#xff0c;人工智能模型正在趋同。 麻省理工学院最近的一篇论文引起了我的注意&#xff0c;因为它提出了一个令人印象深刻的观点&#xff1a;人工智能模型正在趋同&#xff0c;甚至跨越了不同的模态…

GeoScene产品学习视频收集

1、易智瑞运营的极思课堂https://www.geosceneonline.cn/learn/library 2、历年易智瑞技术公开课视频资料 链接&#xff1a;技术公开课-易智瑞信息技术有限公司&#xff0c;GIS/地理信息系统&#xff0c;空间分析-制图-位置智能-地图 3、一些关于GeoScene系列产品和技术操作的…

计算机-编程相关

在 Linux 中、一切都是文件、硬件设备是文件、管道是文件、网络套接字也是文件。 for https://juejin.cn/post/6844904103437582344 fork 进程的一些问题 fork 函数比较特殊、一次调用会返回两次。在父进程和子进程都会返回。 每个进程在内核中都是一个 taskstruct 结构、for…