C++ Primer Plus 学习笔记(七)——STL

1 auto_ptr

auto_ptr模板定义了类似指针的对象,是一种智能指针,当auto_ptr对象过期时,其析构函数将使用delete来释放内存。

void test1()
{
    int* ip = new int(10); //动态内存未释放
    return;
}

void test2()
{
    auto_ptr<int> ip(new int(10)); //auto_ptr对象过期后,会释放动态内存
    return;
}

注意,只能对new分配的内存使用auto_ptr对象,而不要对由new[]分配的或通过声明变量分配的内存使用它。

2 STL

STL提供了一组表示容器、迭代器、函数对象和算法的模板。

STL是一种通用编程技术,模板提供了存储在容器中的数据类型的通用表示,迭代器则是遍历容器中的值的通用表示。

2.1 容器

2.1.1 容器概念

容器概念描述了所有容器类都通用的元素,换句话说,容器概念指定了所有STL容器类都必须满足的一系列要求。

请添加图片描述

可以通过添加要求来改进基本的容器概念。

2.1.2 容器类型

各种容器模板都接受一个可选的模板参数,该参数指定使用哪个分配器对象来管理内存,例如vector模板:

template<typename _Tp, typename _Alloc = std::allocator<_Tp> >

class vector : protected _Vector_base<_Tp, _Alloc> {…}

deque、list、queue、priority_queue、stack 和 vector 都是序列类型容器。

序列(sequence)概念增加了迭代器至少是正向迭代器的要求,以保证元素按特定的顺序排列,不会在两次迭代之间发生变化。

set、multiset、map 和 multimap 都是联合类型容器。

联合容器将值与关键字关联在一起,使用关键字来查找值。

2.2 迭代器

STL定义了5种迭代器——输入迭代器、输出迭代器、正向迭代器、双向迭代器、随机访问迭代器。

为何需要这么多迭代器呢?目的是为了在编写算法时尽可能使用要求最低的迭代器,并让它适用于容器的最大区间。

  • 输入迭代器:对于单通行、只读算法,可以使用输入迭代器。
  • 输出迭代器:对于单通行、只写算法,可以使用输出迭代器。
  • 正向迭代器:具有输入/输出迭代器的所有特性,同时还支持多次通行算法。
  • 双向迭代器:具有正向迭代器的所有特性,同时支持双向遍历容器。
  • 随机访问迭代器:具有双向迭代器的所有特性,同时添加了支持随机访问的操作和用于对元素进行排序的关系操作符。

请添加图片描述

STL根据所需的迭代器类型对算法进行了描述,例如 find() 的原型指出,这种算法需要一个输入迭代器。

template <class InputIterator, class T>
InputIterator find (InputIterator first, InputIterator last, const T& value);
2.2.1 指针作为迭代器

迭代器是广义指针,而指针满足所有的迭代器要求,因此STL算法可以使用指针来对基于指针的非STL容器进行操作。

例如,使用 sort() 对数组进行排序:

double nums[10];

sort(nums, nums + 10);

2.2.2 其他迭代器

头文件<Iterator>还提供了 ostream_iterator、istream_iterator、reverse_iterator、back_insert_iterator、front_insert_iterator 和 insert_iterator 这些专用的预定义迭代器类型。

2.3 函数对象

很多STL算法都使用函数对象——也叫函数符(functor)。函数符是可以以函数方式与()结合使用的任意对象,这包括函数名、指向函数的指针和重载了()操作符的类对象(即定义了函数operator()()的类)。

2.3.1 函数符概念

STL也定义了函数符概念:

  • 生成器:不用参数就可以调用的函数符。
  • 一元函数:用一个参数可以调用的函数符。
  • 二元函数:用两个参数可以调用的函数符。

对应的改进版概念:

  • 返回bool值的一元函数是断言。
  • 返回bool值的二元函数是二元断言。

例如, sort() 函数可以将二元断言作为其第3个参数:

bool Compare(const Book& book1, const Book& books);
...
sort(books.begin(), books.end(), Compare);
2.3.2 预定义函数符

为了支持将函数作为参数的STL函数,STL定义了多个基本函数符,它们执行诸如将两个值相加、比较两个值是否相等操作。

请添加图片描述

例如,假设需要对两个数组进行相加,普通实现和使用预定义函数符的实现为:

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <Iterator>

using namespace std;

double add(double d1, double d2) { return d1 + d2; }

int main()
{
    ostream_iterator<double, char> out(cout, " ");
    vector<double> ds1 = { 1.1, 2.2, 3.3, 4.4 };
    vector<double> ds2 = { 1, 2, 3, 4 };

    // 1、普通实现必须为每种类型单独定义一个函数
    transform(ds1.begin(), ds1.end(), ds2.begin(), out, add);

    cout << endl;

    // 2、更好的办法是定义一个模板,而STL就已经预定义好了这么一个模板
    plus<double> add2;
    transform(ds1.begin(), ds1.end(), ds2.begin(), out, add2);
}
2.3.3 函数适配器(已废弃)

如果 STL 函数需要一个一元函数,而现有一个能完成相应工作的自适应二元函数,则可以使用 bind1st 或 bind2nd 使该二元函数适应于一元接口。

#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
#include <Iterator>
#include <binders.h>

using namespace std;

double sqrt(double d1) { return d1 * 2.5; }

int main()
{
    ostream_iterator<double, char> out(cout, " ");
    vector<double> ds1 = { 1.1, 2.2, 3.3, 4.4 };

    // 1、普通实现
    transform(ds1.begin(), ds1.end(), out, sqrt);

    cout << endl;

    // 2、另外一种实现是,将现有能实现该功能的二元函数适配为一元函数
    transform(ds1.begin(), ds1.end(), out, binder1st<multiplies<double>>(multiplies<double>(), 2.5));
}

2.4 算法

对于算法函数设计,有两个主要的通用部分。首先,它们都使用模板来提供通用类型;其次,它们都使用迭代器来提供访问容器中数据的通用表示。

2.4.1 算法组

STL 将算法库分为4组:

  • 非修改式序列操作。
  • 修改式序列操作。
  • 排序和相关操作。
  • 通用数字计算。
2.4.2 函数和容器方法

相较于 STL 函数,STL 方法通常是更好的选择。首先,它更适合于特定的容器;其次,作为成员函数,它可以使用模板类的内存管理工具从而在需要时调整容器的长度。

2.5 其他库

Complex 头文件为复数提供了一个 complex 类模板,专用于 float、long 和 long double。

valarray 头文件提供了 valarray 模板类,被设计成用于表示数值数组,支持各种数值数组操作。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值