C++高阶-初识STL

STL概念

算法 + 容器 + 迭代器 = STL(Standard Template Library)
STL,即标准模板库,是一个具有工业强度的、高效的 C++函数库。
STL 主要分成三大核心部分:算法( algorithm)、容器( container)和迭代器( iterator)。除此之外还有容器适配器( container adaptor)、函数对象( functor)等。几乎 STL 的所有代码都采用了模板类和模板函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

容器

在程序中,我们总是使用各种数据结构(比如链表、 队列等)来组织数据并对其进行管理。常用的数据结构数量有限,并且每个人实现的相同数据结构的代码都十分相似,仅仅是为了适应不同的数据类型变化而在细节上有所出入而已。正是因为这一点, STL 容器允许重复利用已有的实现,它提供了一些基础数据结构的模板类,比如list<T>、 queue<T>等,我们通过设置特定数据类型为模板参数T,就可以构造出自己的特定类型下的数据结构。通过这种方式,我们将那些重复而乏味的基础数据结构的构造工作简化,从而大大提高了开发效率。

算法

算法是应用在容器上的以各种方法处理容器中数据的行为。跟数据结构一样,程序中的算法同样也有很大的通用性,你开发的稳定性排序算法跟我开发的稳定性排序算法在本质上是一样的,最多只是在操作不同数据类型的数据上有所差异。相同的轮子,没必要重复发明两次。 STL 将编程时常见的一些通用算法收集起来,同时通过迭代器跟容器配合使用,使它可以适应不同的数据结构和数据类型。当我们需要使用这些通用算法时,直接使用 STL 提供的版本就行了,比如直接使用 STL 中的stable_sort()函数配合容器就可以完成数据的稳定性排序,无需我们自己再去实现一次。这样就做到了很好的代码复用,提高了开发效率。

迭代器

如果容器用于容纳数据、算法用于处理数据,那么迭代器就像胶水一样将算法和容器紧密地结合在一起。 迭代器提供了一种统一的接口供算法访问各种容器中的数据。 这就使得算法的实现与容器的具体类型无关。 如果没有迭代器,处理数据的算法就很可能和容纳数据的容器相互分离了,为了处理容器中的数据,我们不得不指定特定的容器实现特定的算法,这样会让数据和算法藕合在一起,为某种容器实现的算法无法操作另一种容器,算法丧失了它的通用型知。

总结:STL 中的这三大组成部分,容器负责容纳数据,算法负责处理数据,而迭代器正好将两者联系在一起。正是算法、容器和迭代器这三个核心部分相互配合、相互作用,使得 STL 成为了一个有机的整体。

在程序中使用STL

因为STL 已经是 C++标准库的一部分,所以无须其他额外操作就可以在 C++代码中直接使用STL。
根据功能的不同, STL 中的各个容器和算法被组织在多个头文件中,要想在程序代码中简单地使用STL,只需要引入相应的头文件,并使用对应的 std 名字空间即可。
在这里插入图片描述
在这里插入图片描述
先来看个实际的例子,将 STL 应用到一个工资程序中,

// …
#include <vector> // 为了使用 vector 容器
#include <algorithm> // 为了使用 count_if()算法
using namespace std; // 使用 std 名字空间
// …
// 使用 STL 改写后的可以统计高工资员工数的 SalarySys 类
class SalarySys
{
// …
public:
// …
int GetMaxCount()
{
	int nTotal = 0;
	// 使用 count_if()算法统计工资大于 1000 的员工人数
	nTotal = count_if(m_vecEmp.begin(), // 统计范围开始
	m_vecEmp.end(), // 统计范围结束
	[=](Employee* p)->bool // 统计规则
	{
		return p->GetSalary() > 1000;
	});
	return nTotal; // 返回统计结果
}
// …
private:
	vector<Employee*> m_vecEmp; // 使用容器取代数组
};

在这段程序中,我们使用了 vector 容器代替数组来组织和管理员工数据,同时使用了 count_if()算法代替 for 循环来完成符合条件(工资大于 1000)员工的统计。

用 vector 容器取代数组管理数据,内存空间的使用更加合理。虽然使用数组可以管理员工数据,但数组有一个天然的缺点——它的大小是固定的。我们必须在定义数组的时候就指定数组的大小,而正是固定不变的大小给它的使用带来了麻烦:如果一开始定义的数组过大,但数据不够多,最后会造成内存资源的浪费。反过来,如果一开始定义的数组过小而数据又比较多,那么就会出现数组空间不够用的情况,不利于程序的扩展。使用 vector 容器很好地弥补了数组的缺点,完美地解决了上面的问题。 vector 容器的大小不是固定的,它可以根据我们的需要动态地自动调整,如果数据较多,它就会自动调大自己的容量,反过来,如果数据较少,它又会自动调小自己的容量。这样一来,vector 容器既不会浪费内存资源,也不会出现容量不够的情况,对内存的使用就更加合理。

用 count_if()算法取代 for 循环提高了开发效率,增加了程序的可维护性。 使用 for 循环来统计数组中工资大于 1000 元的员工人数虽然管用,但是显得很生硬。首先,for 循环需要知道数组中已经保存的有效员工数,这就需要增加一个额外的变量来记录。另外,如果想对其进行扩展,统计其他工资范围内的员工个数, 或者是统计其他项目, 那么还需要写另外一个 for 循环,这样会使得整个程序变得纷繁复杂,降低了开发效率,同时也增加了后期的维护成本。如果使用 STL 中的 count_if()算法,再配合使用 vector 容器,就可以很好地解决这些问题。 通过 vector 的 begin()和 end()函数,我们可以方便地得到统计范围,而通过 count_if 算法中的Lambda 表达式, 我们可以自由定义统计规则.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值