STL简介

        STL,即标准模板库(Standard Template Library)。STL提供了一些常用的数据结构和算法。例如vector就是STL提供的一个容器,排序、顺序查找、折半查找算法等算法在STL中都有现成的函数模板。然而,这并不是STL的全部。STL更大的意义在于它定义了一套概念体系,为泛型程序设计提供了逻辑基础。

下面通过程序来简单了解STL:

//从标准输入读入几个整数,存入vector容器中,再利用STL输出它们的相反数
#include <vector>
#include <string>
#include <iterator>
#include <algorithm>
#include <functional>
#include <iostream>
using namespace std;

int main()
{
    int n = 5;
    vector<int> vec(n);
    //从标准输入读入向量容器的内容
    for (int i = 0; i < n; i++)
    {
	cin >> vec[i];
    }
    //输出相反数
    transform(vec.begin(), vec.end(), ostream_iterator<int>(cout, " "), negate<int>());
    cout << endl;
    return 0;
}

这个简单的程序涉及到了STL的最基本的四种组件:容器、迭代器、算法、函数对象。

1.容器(container)

          容器是容纳一组元素的对象。容器类库中包含7中基本容器:向量(vector)、双端队列(deque)、列表(list)、集合(set)、多重集合(multiset)、映射(map)、多重映射(multimap)。上述例子中的vector就是一个最简单的容器。

2.迭代器(iterator)

        迭代器提供了顺序访问容器中每个元素的方法。对迭代器可以使用“++”运算符来获得指向下一个元素的迭代器,可以使用“*”运算符访问一个迭代器所指向的元素。如果元素类型是类或结构体,还可以使用“->”运算符直接访问该元素的一个成员,有些迭代器还支持通过“--”运算符获得指向上一个元素的迭代器。指针也具有同样的特性,因此指针本身就是一种迭代器,迭代器是泛化的指针。上述例子中的vec.begin()、vec.end()以及ostream_iterator<int> (cout," ")都是迭代器。

迭代器的作用:迭代器模式又称游标模式,用于提供一种方法顺序访问一个聚合对象中各个元素,而又不需要暴露该对象的内部表示,或者说迭代器模式是运用于聚合对象的一种模式,通过运用该模式,使得我们可以在不知道对象内部表示的情况下,按照一定顺序访问聚合对象中的各个元素。

迭代器和指针的区别:迭代器不是指针,是类模板,只是表现的像指针而已。迭代器只是模拟了指针的一些功能,通过重载了指针的一些操作符,如“->”,“*”,“++”,“--”等。迭代器封装了指针,是一个可遍历STL容器内全部或部分元素的对象,本质上是封装了原生指针,是指针概念的一种提升,提供了比指针更高级的行为,相当于以一种智能指针,它可以根据不同类型的数据结构来实现不同的“++”、“--”等操作。迭代器返回的是对象引用而不是对象的值,所以cout只能输出迭代器使用*取值后的值而不能直接输出其自身。

3.函数对象(function object)

        函数对象是一个行为类似函数的对象,对它可以像调用函数一样调用。任何普通的函数和任何重载了“()”运算符的类的对象都可以作为函数的对象使用,函数对象是泛化的函数。上述例子中的“negate<int> ()”就是一个函数对象。negate是一个类模板,它重载了的“()”运算符接收一个参数,该运算符返回的就是该参数的相反数。negate的模板参数int表示的是negate的“()”运算符接受和返回参数的类型。

4.算法(algorithm)

       STL包含70多种算法,这些算法覆盖了相当大的领域,其中包括查找算法、排序算法、消除算法、计数算法、比较算法、变换算法、置换算法和容器管理等。这些算法的一个最重要的特性就是它们的统一性,并且可以广泛用于不同的对象和内置的数据类型。上述例子中的transform就是一个算法。

STL中四种组件的基本关系为:STL把迭代器作为算法的参数,通过迭代器来访问容器而不是把容器直接作为算法的参数;STL把函数对象作为算法的参数而不是把函数所执行的运算作为算法的一部分。

迭代器的分类

1.输入迭代器

输入迭代器用来从序列中读取数据,但是不一定能够向其中写入数据。输出迭代器支持对序列进行不可重复的单向遍历。

p1 == p2          两个输入迭代器可以用“==”来比较是否相等

p1 != p2           两个输入迭代器可以用“!=”来比较是否不同,等价于!(p1 == p2)

*p1                  可以使用“*”获取输入迭代器所指向元素的值,该表达式返回值可以转换为T类型

p1 -> m           等价于(*p1).m

*p1++              对输入迭代器而言,尽管p1++的返回值类型不是确定的,但是*(p1++)的值是确定的

        除此之外,需要注意的是,如果p1 == p2,并不能保证++p1 == ++p2,更不能保证*(++p1) == *(++p2)。由于这一点,用输入迭代器读入的序列不能保证是可重复的。因此,输入迭代器只适用于作为那些只需要遍历序列一次的算法的输入。

2.输出迭代器

输出迭代器允许从序列中写入数据,但是并不保证可以从其中读取数据。输出迭代器也支持对序列进行单向遍历。

*p1 = t            向迭代器所指向位置写入一个元素,返回类型不确定

*p1++ = t        等价于{*p1 = t;++p1},返回类型不确定

        另外,使用输出迭代器,写入元素的操作和使用“++”自增的操作必须交替进行。如果连续两次自增之间没有写入元素,或连续两次使用“*p1 == t”这样的语法写入元素之间没有自增,其行为都是不确定的。

3.前向迭代器

        前向迭代器这一概念是输入迭代器和输出迭代器这两个概念的子概念,它既支持数据读取,也支持数据写入。前向迭代器支持对序列进行可重复的单向遍历。它去掉了输入迭代器和输出迭代器这两个概念中的一些不确定性。对于前向迭代器,如果p1 == p2,那么++p1 == ++p2是一定会成立的,这就意味着前后两次使用相等的输入迭代器遍历一个序列,只要序列的值在这个过程种没有被改写,就一定会得到相同的结果,因此前向迭代器对序列的遍历是可重复的。另外,前向迭代器不再有输出迭代器关于“++”自增操作和对元素的写入操作必须交替进行的限制。

*p1         对前向迭代器使用“*”运算符的结果保证具有T&类型

p1++      对迭代器实例可以使用后置“++”使迭代器指向下一个元素,该表达式的返回类型为P,其值为{p2 = p1;++p1;return p2;}

前向迭代器适用于单向链表中,只能“++”,不能“--”。

4.双向迭代器

双向迭代器这一概念是单向迭代器的子概念。在单向迭代器所支持的功能基础上,它又支持迭代器向反方向移动。

--p1      可以使用前置“--”运算符使迭代器指向上一个元素,返回值为p1自身的引用

p1--      可以使用后置“--”运算符使迭代器指向上一个元素,返回值类型为X,其值为{p2 = p1;--p1;return p2}

5.随机访问迭代器

随机访问迭代器这一概念是双向迭代器的子概念。在双向迭代器的基础上,它又支持直接将迭代器向前或向后移动n个元素,因此随机访问迭代器的功能几乎和指针一样。

p1 += n                         将迭代器p1向后移动n个元素

p1 -= n                          将迭代器p1向前移动n个元素

p1 + n或n + p1             获得指向迭代器p1前第n个元素的迭代器

p1 - n                           获得指向迭代器p1后第n个元素的迭代器

p1 - p2                         返回一个满足p1 == p2 + n的整数n

p1 op p2                      op可以是<,<=,>,>=,用于比较p1和p2所指向位置的前后关系,等价于p1 - p2 op 0

p1[n]                            等价于*(p1 + [n])

通过向量容器vector的begin()和end()函数得到的迭代器就是随机访问迭代器,指针也是随机访问迭代器。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值