马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
目次
编辑
一、STL 是什么?
二、STL的六大组件
容器(Containers)
迭代器(Iterators)
算法(Algorithms)
函数对象(Function Objects)
适配器(Adapters)
空间设置器(Allocator)
三、为什么要用 STL?
一、STL 是什么?
STL 是 C++ 标准库的一部门,它提供了一系列通用的模板类和函数模板,这些模板都是颠末经心筹划和优化的,可以用来处理处罚各种常见的编程使命,比如数据存储(像数组、链表、树这些结构干系的事儿)、数据处理处罚(排序、查找等利用)以及算法实现等。简单说呢,就是别人已经帮咱们把很多常用的、好用的代码模板都准备好了,咱们只要知道怎么用就行了。
二、STL的六大组件
STL(Standard Template Library,标准模板库)告急由以下六大组件构成,每个组件在 STL 体系中都起着至关告急的作用,它们相互协作,为 C++ 步伐员提供了强大且便捷的编程工具。
容器(Containers)
容器是用于存储数据元素的对象,STL 提供了多种差异范例的容器,以满足各种数据存储和利用需求。
- 次序容器(Sequential Containers):
- vector:类似于动态数组,可以在运行时动态调解巨细。元素在内存中是连续存储的,这使得它可以或许快速地随机访问元素,但在中心插入或删除元素时,大概须要移动大量其他元素。比方,vector<int> vec; vec.push_back(1); vec.push_back(2);创建了一个存放整数的vector容器,并依次添加了两个元素。
- list:是一个双向链表结构,每个节点包罗一个数据元素以及指向前一个和后一个节点的指针。在链表中心插入和删除元素相对容易,只需调解干系节点的指针即可,不外随机访问元素的速率相对较慢,由于须要从链表头或链表尾逐个遍历节点才华访问到目的元素。比如,list<int> lst; lst.push_back(1); lst.push_back(2);创建了一个存放整数的list容器并添加了两个元素。
- deque:即双端队列,它团结了数组和链表的一些特点。在两端(头部和尾部)可以像链表一样方便地插入和删除元素,同时又能像数组一样支持快速的随机访问(但随机访问速率比vector稍慢一些)。比方,deque<int> dq; dq.push_back(1); dq.push_back(2); dq.push_front(3);创建了一个存放整数的deque容器,不但能从尾部添加元素,还能重新部添加元素。
- 关联容器(Associative Containers):
- set:是一种存储唯一元素的容器,它会自动按照元素的某种特定次序(通常是根据元素的比力函数确定的次序,如对于整数是按照巨细次序,对于字符串是按照字典序)对元素举行排序。比方,set<int> s; s.insert(3); s.insert(1); s.insert(2);创建了一个存放整数的set容器,并插入了几个元素,插入后元素会自动按照从小到大的次序分列。当试图插入一个已经存在于set中的元素时,插入利用将不会乐成,由于set要包管元素的唯一性。
- map:它是一种键值对容器,每个元素由一个键(key)和一个值(value)构成。通过键可以快速地找到对应的 值,而且键在总体内是唯一的。比方,map<int, string> m; m.insert(make_pair(1, "one")); m.insert(make_pair(2, "one"));创建了一个存放整数键和字符串值的map容器,并插入了两对键值对。类似于set,map也会根据键的比力函数自动对键值对举行排序,以便于快速查找。
迭代器(Iterators)
迭代器是一种类似于指针的对象,它提供了一种同一的方式来访问容器中的元素,使得步伐员可以在不相识容器内部实现细节的情况下,对差异范例的容器举行遍历、修改等利用。
- 差异范例的容器有差异范例的迭代器,比如:
- 正向迭代器:用于按照容器中元素的存储次序从前今后遍历元素。比方,对于vector<int>容器,vector<int>::iterator it = vec.begin();,这里vec.begin()返回的就是指向容器第一个元素的正向迭代器,通过it++可以逐个访问反面的元素。
- 反向迭代器:用于按照与容器中元素存储次序相反的方向从后往前遍历元素。比方,对于list<int>容器,list<int>::reverse_iterator rit = lst.rbegin();,这里lst.rbegin()返回的就是指向容器末了一个元素的反向迭代器,通过rit--可以逐个访问前面的元素。
- 常量迭代器:用于在不修改容器元素的情况下遍历元素,有正向常量迭代器和反向常量迭代器之分。比方,对于set<int>容器,set<int>::const_iterator cit = s.begin();,在这种情况下,固然可以访问元素,但不能对其举行修改。
算法(Algorithms)
STL 提供了大量的算法来对容器中的元素举行各种利用,这些算法通过迭代器来指定利用的范围,从而实现了对差异范例容器的通用性。
- 排序算法(Sorting Algorithms):
- std::sort:这是最常用的排序算法之一,它可以对一个给定范围内的元素举行快速排序。比方,对于vector<int>容器vec,std::sort(vec.begin(), vec.end());会将容器中的整数按照从小到大的次序分列。它的时间复杂度通常为 O (n log n),此中 n 是要排序的元素个数。
- std::stable_sort:与std::sort类似,但它在排序过程中会包管相称元素的相对次序稳定。比方,在对一个包罗重复元素的容器排序时,如果利用std::stable_sort,那么原来在前面的重复元素在排序后仍然会在前面。
- 查找算法(Searching Algorithms):
- std::find:用于在一个给定范围内探求指定的元素。比方,对于list<int>容器lst,std::find(lst.begin(), lst.end(), 5);会在容器中探求整数 5,如果找到则返回指向该元素的迭代器,否则返回一个特别的标志(如list<int>::end()),表现没有找到。
- std::binary_search:实用于已经排序的容器,它利用二分法来快速查找指定的元素。比方,对于已经排序好的vector<int>容器vec,std::binary_search(vec.begin(), vec.end(), 5);会判断容器中是否存在整数 5。如果存在,返回 true;否则,返回 false。
- 其他算法(Other Algorithms):
- std::copy:用于将一个范围内的元素复制到另一个位置。比方,对于vector<int>容器vec1和vec2,std::copy(vec1.begin(), vec1.end(), vec2.begin());会将vec1的全部元素复制到vec2的开头部门。
- std::accumulate:用于盘算一个范围内的元素的总和或其他可累积的属性。比方,对于vector<int>容器vec,std::accumulate(vec.begin(), vec.end(), 0);会盘算容器中全部元素的总和,这里第二个参数 0 表现初始值。
函数对象(Function Objects)
函数对象,也称为仿函数(Functors),是一种可以像函数一样被调用的对象。它们在 STL 中有偏告急的作用,常常被用来替换寻常的函数作为算法的参数,以实现更机动的利用。
- 比方,界说一个比力函数对象来实现特定的比力规则:
- class MyComparator { public: bool operator()(int a, int b) { return a > b; } };
- 这里界说了一个名为MyComparator的函数对象,它实现了一个比力规则,即比力两个整数时,返回较大的数在前的效果。可以将这个函数对象作为参数传给std::sort算法,比方:vector<int> vec; vec.push_back(1); vec.push_back(2); std::sort(vec.begin(), vec.end(), MyComparator());,如许就会按照我们界说的比力规则(较大数在前)对容器中的元素举行排序。
适配器(Adapters)
适配器是一种将一种接口转换为另一种接口的组件,在 STL 中告急用于将差异范例的容器、迭代器或函数对象举行转换,以满足特定的应用需求。
- 容器适配器(Container Adapters):
- stack:它是基于其他容器(如vector、list等)实现的一种后进先出(LIFO)的数据结构。比方,以vector为底子实现的stack可以如许创建:stack<int, vector<int>> stk;,这里第一个参数表现栈中元素的范例,第二个参数表现所基于的容器范例。通过push、pop等利用可以对栈举行利用。
- queue:也是基于其他容器(如vector、list等)实现的一种数据结构,不外它是先辈先出(FIFO)的。比方,以list为底子实现的queue可以如许创建:queue<int, list<int>> q;,同样,通过push、push_front、pop等利用可以对队枚举行利用。
- 迭代器适配器(Iterator Adapters):
- reverse_iterator:它是一种将正向迭代器转换为反向迭代器的适配器。比方,对于vector<int>容器vec,vector<int>::reverse_iterator rit = vec.rbegin();,这里vec.rbegin()就是利用reverse_iterator适配器将正向迭代器转换为反向迭代器的效果,通过rit--可以按照与容器中元素存储次序相反的方向从后往前遍历元素。
- 函数对象适配器(Function Object Adapters):
- bind:它是一种将函数对象与参数举行绑定的适配器。比方,假设有一个函数对象MyFunction和一些参数,通过bind可以将这些参数绑定到MyFunction上,形成一个新的函数对象,以便于在特定的应用场景下利用。
空间设置器(Allocator)
空间设置器是负责为容器分配和接纳内存空间的组件。它就像是一个幕后的 “内存管家”,当容器须要存储新的元素、扩展容量等情况时,就由空间设置器来处理处罚干系的内存利用,确保容器可以或许顺遂地获取到所需的内存空间,而且在元素被移除或容器被烧毁时,公道地接纳内存,克制内存走漏等标题。
- 一级空间设置器(__malloc_alloc_template):现实上是对malloc和free函数的一种包装。它在内部根本就是直接调用malloc函数来分配内存,调用free函数来接纳内存。比方,当容器须要分配肯定巨细的内存空间时,一级空间设置器会像如许利用:void* ptr = __malloc_alloc_template<>::allocate(n);,这里n是须要分配的 ,__malloc_alloc_template<>::allocate函数内部就是调用malloc函数来完因素配的。
- 二级空间设置器(__allocator_base):引入了内存池的概念。它会预先分配一块较大的内存池,然后从这个内存池中为容器分配所需的内存空间。比如,它大概会先分配一块 16KB 的内存池,当容器须要分配内存时,就从这个内存池中取出符合巨细的 ,以便给容器。对于较小的内存块(通常界说为小于即是 128 字节),二级空间设置器会利用一种叫做 “自由链表” 的结构来管理。自由链表就是把同范例(即雷同巨细)的空闲内存块用链表的情势毗连起来,当须要分配这种小内存块时,就从相应的自由链表中取出一个空闲块给容器;当容器开释这种小内存块时,又会把它放回相应的自由链表中,以便下次再利用。对于较大的内存块(大于 128 字节),二级空间设置器会像一级空间设置器一样,直接调用malloc函数来分配内存,并在接纳时调用free函数。
这就是 STL 的六大组件啦,它们相互共同,为 C++ 步伐员提供了高效、便捷的编程体验,使得处理处罚各种数据结构和算法标题变得更加容易。
三、为什么要用 STL?
- 进步开辟服从:不消再重新去写那些处理处罚数据结构和算法的代码啦,直接拿 STL 里的现成模板来用就行,能节流大量的时间和精神,让我们可以把更多的心思放在办理具体的业务标题上呢。
- 代码质量包管:STL 里的模板都是颠末专业职员经心筹划和优化的,以是在性能、稳固性等方面都有很好的表现。利用 STL 可以让我们的代码质量更高,镌汰由于自己编写代码不妥而导致的各种标题呢。
- 代码的通用性和可移植性:由于 STL 是 C++ 标准库的一部门,以是在任何支持 C++ 标准的情况下都可以利用,这使得我们的代码具有很好的通用性和可移植性,不管是在 Windows、Linux 还是其他利用体系上,只要是 C++ 能跑的地方,STL 就能派上用场啦。
本篇博客只是对STL开端认识,反面会对STL中的东西具体解说,欢迎品评区留言
|