C++标准模板库STL

标准模板库(standard template library,STL)是C++十分强大的库,其提供了一组表示容器、蝶代替、函数对象和算法的模板。STL实际上是使用泛型编程(generic programming)编写的,其建立在一些概念的抽象之上,如容器、迭代器、分配器等。OOP和泛型编程的理念不同,OOP关注编程的数据表示,泛型编程关注的则是算法,拥有更高的抽象水平。

以下介绍STL中的泛型编程的理念、容器类、迭代器、算法以及函数对象。

目录

泛型编程

迭代器

函数对象

容器类

序列

关联容器

无序关联容器

算法


泛型编程

为了能够让泛型编程能够适用于许多类型,泛型编程主要通过类模板和函数模板以及各种抽象概念实现。抽象概念包括分配器、迭代器、容器等。这些抽象概念有对应具体的类,如allocator类、iteration类等。

  1. STL的几个术语——概念、改进与模型

    概念(concept)指的是描述的要求,如对迭代器的基本要求。改进(refinement)指的是概念的继承,如正向迭代器对于输入迭代器、输出迭代器是改进。模型(model)指的是具体实现,例如C++中的iterator类是迭代器的模型。
     
  2. 分配器Allocator

    分配器Allocator是管理内存的对象。
     
  3. 迭代器Iterator

    迭代器是能够用来遍历容器的对象,其使得算法可以独立于容器类、具体类型。

    迭代器Iterator实际上是满足以下基本概念(concept,STL术语,指一系列要求)的“对象”:
    ①能解除引用以访问引用值,即定义了解除引用运算符*
    ②能够实现迭代器之间的复制,即定义了赋值运算符=
    ③能够实现迭代器之间的比较,即定义了==与!=运算符
    ④能够遍历容器中的每个对象,即定义了++运算符

    从上述要求来看,其实指针和类都可以作为迭代器的具体实现,实际上迭代器就是广义指针。
     
  4. 容器Container

    容器Container则是可以按照一定结构储存数值的对象,比如数组、链表等。在STL中,容器都是同质的,只能放相同类型的值。
     
  5. 函数对象

    函数对象是类似于函数的对象,也叫函数符(functor),其指的是可以以函数方式与()结合使用的任意对象。函数名、函数指针、重载了()运算符的类都是函数对象。

迭代器

迭代器是一种概念的抽象,也有具体的实现(即iterator类)。不同算法对迭代器的要求不同,根据不同要求(读写数据、遍历方向、随机访问),其分为5类。每种迭代器均能够满足前文提及的概念,但也具有各自不同的概念。

实际上,这5类迭代器具有一定继承关系:正向迭代器继承了输入迭代器、输出迭代器的所有特点;双向迭代器继承了正向迭代器的所有特点;随机迭代器继承了双向迭代器的所有特点

  1. 输入迭代器InputIterator

    输入迭代器指的是能从容器中读取信息(但不一定可以修改)的迭代器。其允许读取,但不允许修改。输入迭代器是单向迭代器,只能前进,不能倒退,并且不保证第二遍遍历顺序不变,也不能保证先前值可以被解除引用(是说不能保存先前值后再解除引用?)。

    使用输入迭代器的算法必须是单通行(single pass)的,不依赖于前一次遍历时的迭代器值,也不依赖于本次遍历中前面迭代器值(?)
     
  2. 输出迭代器OutputIterator

    输出迭代器指能从程序中读取并储存信息到容器的迭代器。其允许解除引用以修改容器值,但不允许读取
     
  3. 正向迭代器Forward Iterator

    正向迭代器只使用++遍历但其每次的遍历顺序相同,并且可以对先前值解除引用(若保存先前值的话),同时可读可写数据(声明const常量即成为只读迭代器)

    使用正向迭代器的算法可以是多通行的。
     
  4. 双向迭代器

    双向迭代器具有正向迭代器所有特点,但允许前进和倒退,因为它定义了++和--两类运算符。
     
  5. 随机访问迭代器
    随机访问迭代器具有双向迭代器的所有特点,但允许随机访问(即访问容器中任意元素)。
     
  6. C++中一些预定义的迭代器
    C++提供了具体的迭代器模型,如ostream_iterator、istream_iterator、reverse_iterator、back_insert_iterator、front_insert_iterator等。它们都包含在头文件iterator中。

    · ostream_iterator
    ostream_iterator是输出迭代器的模型。其声明的代码如下:
    /*声明:
    ostream_iterator<被发送给输出流的类型,输出流的类型> 迭代器对象名(输出流);//构造函数1
    ostream_iterator<被发送给输出流的类型,输出流的类型> 迭代器对象名(输出流,数据项的分隔符);//构造函数2
    */
    
    //示例
    ostream_iterator objOI(cout);

    · istream_iterator
    istream_iterator是输入迭代器的模型。其构造函数和ostream_iterator相近:
    /*声明:
    istream_iterator<输入流读取的类型,输入流的类型> 迭代器对象名(输入流);//构造函数1
    istream_iterator<输入流读取的类型,输入流的类型> 迭代器对象名(输入流,数据项的分隔符);//构造函数2
    */
    
    //示例
    istream_iterator objII(cin);

    · reverse_iterator反向迭代器

    reverse_iterator是为了简化函数使用而创建的,其指向序列的末端,对其递增实际上使其递减,其指向原对象之前的对象。常用于反序问题。

    · back_insert_iterator、front_insert_iterator、insert_iterator

    这三种迭代器均是为了插入算法服务的,都是输出迭代器的模型,但适用于不同的容器类,因此在声明对象时,都需要声明相应的容器类型。

    #back_insert_iterator将元素插入到末尾只能用于允许在尾部插入的容器(如队列queue)
    #front_insert_iterator将元素插入到前端只能用于允许在头部插入的容器(如栈stack、双向队列dequeue)
    #insert_iterator则将元素插入到指定位置前,该指定位置通过insert_iterator的构造函数传入

    三种迭代器的构造函数如下:
    /*构造函数
    back_insert_iterator<容器类型> 迭代器名(类型对应的容器对象);
    front_insert_iterator<容器类型> 迭代器名(类型对应的容器对象);
    insert_iterator<容器类型> 迭代器名(类型对应的容器对象,插入位置);
    //插入位置实际上也是个迭代器
    */
    
    //示例
    
    #include
    #include
    #include
    using namespace std;
    vector v(4);
    back_insert_iterator> objBII(v);
    insert_iterator> objII(v,v.begin());
    
    

函数对象

  1. 定义与种类

    函数对象也称为函数符(functor),指的是能够与运算符()结合发挥与函数类似作用的任意对象。函数对象包括函数名、函数指针以及重载了()运算符的类对象
     
  2. 函数符的改进——生成器、一元函数、二元函数、一元谓词、二元谓词

    函数符按照调用参数、返回类型的不同,分为几种类型:
    生成器(generator):不用参数即可调用的函数符。例如默认构造函数就是一种生成器。
    一元函数(unary function):需要使用一个参数即可调用的函数符
    二元函数(binary function):需要使用两个参数即可调用的函数符
    谓词(predicate)返回bool的一元函数称为谓词。
    二元谓词binary predicate):返回bool的二元函数称为二元谓词。
  3. 一些预定义的函数符

    C++在头文件functional中定义了多个模板类函数对象,常用的主要有less<>、greater<>、plus<>等,以下作部分介绍:

    · 预定义的函数符​​​​​
    预定义的函数符和许多运算符相对应:
    运算符 函数符
    + plus
    - minus
    * multiplies
    / divides
    % modulus
    -(取负) negate
    == equal_to
    != not_equal_to
    > greater
    < less
    >= greater_equal
    <= less_equal
    && logical_and
    || logical_or
    ! logical_not

    · 预定义函数符的使用
    这些函数符均是用模板写的,因此调用于生成函数符对象时,需要在尖括号内声明相应的类型
     
    /*
    //调用于生成函数符对象:
    函数符名<类型> 对象名;
    
    //调用函数
    对象名(左值,右值)
    
    //传入容器的构造函数作为比较对象时
    //只需传入函数符即可,不需要加上()
    */
    
    //示例
    void main()
    {
    	plus add;
    	int ans=add(1,2);
    	cout<
  4. 函数符的使用

    · 通过类定义一个函数符

    如前文所说,重载了()运算符的类也可以作为函数符使用,作为比较对象传入容器构造函数时,只需传入类名即可。

    示例代码如下:
    class Greater//类函数符
    {
    public:
    	Greater(const int & val_a,const int & val_b):a(val_a),b(val_b){};
    	~Greater();
    	bool operator()(){return a>b;}//重载()运算符
    
    private:
    	int a;
    	int b;
    };
    
    void main()
    {
    	set objSet;//传入Greater作为比较对象
    }
    上文的代码段中的Greater是针对int类型的,其实也可以像预定义的函数符一样,将其定义为一个类模板,这样其普适性会更强。
     

容器类

容器是按照一定组织结构储存数值的对象,其实就是一系列数据结构的实现(或者用STL的术语来说,模型)。STL中有许多强大的容器类,主要有几大类:

  1. 序列(如单向链表forward_list、双向链表list、队列queue、矢量vector、双向队列dequeue、优先队列/堆priority_queue)
  2. 关联容器(如地图/键值对map、集合set、多重映射multimap)
  3. 无序关联容器(如哈希表unordered_map、unordered_set、unordered_multimap等)。

容器类的基本特征(或者说基本成员)主要有:(X表示序列类型,t为类型T的值,a、b为容器对象,n表示整数,p、q、i、t为迭代器)

表达式 返回类型 说明 时间复杂度
X::iterator - 满足正向迭代器的任何迭代器 编译时间
X::value_type T T的类型 编译时间
X u 创建一个空容器对象u 固定时间
X() 创建一个匿名空容器对象 固定时间
X u(a) 迭代器 调用复制构造函数,使用容器对象a创建容器对象u 线性时间
X u=a void 同X u(a) 线性时间
a.begin() (常量)迭代器 返回指向容器第一个元素的迭代器 固定时间
a.end() 迭代器 返回指向容器超尾(即最后一个元素以后)的迭代器 固定时间
a.size() 整数 返回容器元素数 固定时间
a.swap(b) void 交换a和b的内容 固定时间
a==b bool 如果a、b长度相同,且a、b中的每个元素都相同,则返回真 线性时间
a!=b bool 返回!(a==b) 线性时间

编译时间指操作将在编译时执行,执行时间为0;固定时间、线性时间均表示操作在运行时执行,固定时间但独立于对象的元素数,线性时间则与元素数成正比。

以下主要从容器类的特点、声明、方法。介绍各容器类,可以联系数据结构的内容以加深理解。使用各容器前,记得包含它们各自的头文件,头文件名一般与它们的名称相同。
 

序列

序列是对容器概念的改进,在容器的概念之上,要求:
①迭代器至少应为正向迭代器
②元素应按严格的线性顺序排列


下表总结了每种序列的基本成员的相同部分:(X表示序列类型,t为类型T的值,a为序列对象,n表示整数,p、q、i、t为迭代器)

成员表达式 返回类型 说明
X a(n,t) - 声明一个由n个t组成的序列对象a
X(n,t) 声明一个由n个t组成的匿名序列
X a(i,t) 声明一个由区间[i,j)之间的内容组成的序列对象a
X(i,t) 声明一个由区间[i,j)之间的内容组成的匿名序列
a.insert(p,t) 迭代器 将t插入到p前面
a.insert(p,n,t) void 将n个t插入到p前面
a.insert(p,i,j) void 将区间[i,j)的内容插入到p前面
a.erase(p) 迭代器 删除p
a.erase(p,q) 迭代器 删除区间[p,q)的内容
a.clear() void 清空所有内容

 以下作各序列的简介。各类的方法可以查看相关STL使用目录(例如C++ primer plus第六版的附录G)。

  1. 单向链表forward_list

    单向链表中,每个节点只能链接到下一个节点,即只能前进遍历下一个节点。forward_list使用的是正向迭代器,是不可反转的容器。

    其基本操作与list类似,功能较少但更紧凑。
     
  2. 双向链表list

    双向链表中,除了第一个和最后一个元素外,每个元素都与前后两个节点相链接,即保存有前后两个节点的访问信息。list使用的是双向迭代器,允许双向遍历。list是可反转容器,但不允许随机访问与数组表示法。

    list在删除、插入的操作开销是固定时间,遍历则是线性时间。

    list提供的成员函数如下:(T为元素类型;Alloc为分配器,一般有默认值;N为元素数)
    函数 说明 时间复杂度
    void merge(list&x) 将对象与相同类型的链表x合并 线性时间
    void remove(const T & val) 删除val的所有实例 线性时间
    void sort() 使用<运算符排序 NlogN
    void splice(iterator pos, list x) 将相同类型链表x插入到p位置前,并且x将被置空 固定时间
    void unique() 连续相同元素压缩为单个元素 线性时间
  3. 矢量vector

    矢量vector是动态数组。它提供了元素的随机访问,需要使用随机访问迭代器。

    在尾部删除或插入的时间是固定时间,在头部、序列中间删除或者插入是线性时间。

    vector是可反转容器,含有rend()、rbegin()两个方法:
    函数 返回类型 说明
    void rend() reverse_iterator 返回指向反转序列的末尾元素(即正序第一个元素)的迭代器
    void rbegin() reverse_iterator 返回指向反转序列第一个元素(即正序最后一个元素)的迭代器
  4. 队列queue

    队列queue只允许在头部删除,尾部插入,不允许随机访问/遍历。

    STL中的queue实际上是一个适配器,其让底层类(即实现的基础,STL中默认为deque,实际上也可以用链表、数组实现queue转换成了队列。

    其基本操作如下:
    函数 说明
    bool empty() const 查看队列是否为空
    int size() const 查看队列元素个数
    T & front() 返回头部元素的引用
    T & back() 返回尾部元素的引用
    void push(T &x) 将元素x压入队尾
    void pop() 删除头部元素
  5. 双向队列dequeue(doubled-ended queue)

    双向队列dequeue允许在头部和尾部插入或者删除。其也提供了随机访问的功能,因此需要使用随机访问迭代器。

    其在头部、尾部插入或者删除的时间为固定时间,在序列中间插入或者删除的时间为线性时间。
     
  6. 优先队列/堆priority_queue

    优先队列/堆priority_queue将最大的元素放在队首,在STL中堆的底层类是vector。

    堆支持的操作与queue一样:front()、back()、push()、pop()。堆获取队首元素所需时间是固定时间。声明堆对象时,可以修改用于确定哪个元素放到队首的比较方式:
    /*
    priority_queue<元素类型> 堆对象名;//构造函数1
    priority_queue<元素类型> 堆对象名(greater<元素类型>)//构造函数2
    */
    greater<>是预定义的函数对象。
     
  7. 栈stack

    栈只允许从栈顶插入、删除、访问元素,不允许随机访问、遍历。

    stack允许的操作如下:
    函数 说明
    bool empty() const 查看队列是否为空,若为空返回true,非空则返回false
    int size() const 查看栈元素个数
    T & top() 返回栈顶元素的引用
    void push(const T &x) 将元素x压入栈顶
    void pop() 删除栈顶元素
  8. 静态数组array

    array实际上并不是STL容器,因为其长度是固定的,但是可以将许多STL算法用于array对象,例如copy()、for_each()。

    其允许随机访问、遍历。
     

关联容器

关联容器是对容器概念的改进,其将值与键关联在一起,并使用键查找值。关联容器都提供了对元素的快速访问(其所需时间为固定时间)。关联容器一般通过树实现。

  1. 集合set、multiset

    set、multiset都位于头文件set中。

    set中的键是唯一的,不能存储多个相同值,储存的键就是储存的值,故键值类型是一样的
    。set可以反转,也可以排序。

    multiset中可以储存多个重复值,键值仍然相同,并且是按照一定顺序排列的。其是用红黑树实现的。

    · set和multiset共有的成员
    函数 说明
    X::key_type 键Key,键类型
    X::key_compare 键的比较对象Compare,默认为less
    X::value_compare 值的比较对象Compare,二元谓词类型

    · set的成员函数
    set的成员函数主要与数学意义上的集合操作相同,具体如下:(i、j为set对象A的区间的迭代器, p、q为对象B的区间的迭代器,objOI是输出迭代器,t为类型T对象,c为用于比较的函数对象,迭代器类型为set::iterator
    函数 说明
    set A() 创建键值类型为T的set对象A
    set A(B.begin(), B.end(), c) 创建键值类型为T的set对象A,其内容为对象B的区间[begin, end)的内容,并使用函数对象c作为比较对象,c默认为less
    set_union(i, j, p, q, objOI) 并集,将对象A区间[i,j)、对象B区间[p,q)的内容合并并输出到objOI中。objOI需要是输出迭代器,不能是某个容器对象的begin(),因为begin()返回的是常量迭代器,此时可以用insert_iterator。
    set_difference(i, j, p, q, objOI) 差集,找出对象A区间[i,j)、对象B区间[p,q)相差的内容,并输出到objOI中。
    set_intersection(i, j, p, q, objOI) 交集,找出对象A区间[i,j)、对象B区间[p,q)的相交内容,并输出到objOI中。
    A.find(k) 返回一个迭代器,该迭代器指向键与 k 相同的元素;如果没有找到这样的元素,则返回 a.end()
    A.lower_bound(k) 返回一个迭代器,该迭代器指向第一个键不小于 k 的元素
    A.upper_bound(k) 返回一个迭代器,该迭代器指向第一个键不大于 k 的元素
    A.insert(t) 插入一个值为t的键
    A.insert(p, q) 插入B集合中区间[p,q)的值

    · multiset成员方法
    multiset成员方法如下:
    (i、j为multiset对象A的区间的迭代器, p、q为对象B的区间的迭代器,objOI是输出迭代器,t为类型T对象,c为用于比较的函数对象,迭代器类型为multiset::iterator
     
    函数 说明
    multiset, Alloc=allocator> A() 创建键值类型为T的set对象A,比较对象c默认为less函数对象,分配器Alloc默认为allocator
    multiset A(B.begin(), B.end(), c) 创建键值类型为T的set对象A,其内容为对象B的区间[begin, end)的内容,并使用函数对象c作为比较对象,c默认为less
    A.find(k) 返回一个迭代器,该迭代器指向键与 k 相同的元素;如果没有找到这样的元素,则返回 a.end()
    A.lower_bound(k) 返回一个迭代器,该迭代器指向第一个键不小于 k 的元素
    A.upper_bound(k) 返回一个迭代器,该迭代器指向第一个键不大于 k 的元素
    A.insert(t) 插入一个值为t的键
    A.insert(p, q) 插入B集合中区间[p,q)的值

    · set、multiset的使用
    #include
    #include
    using namespace std;
    
    int main()
    {
    	int arrInt[]={12,2,3,5,6};
    	int array[] = { 0, 2, 1, 4, 3, 6, 5, 7, 8, 9, 0, 7, 6};
    	set objSET(&arrInt[0],&arrInt[4]);
    	cout<<*objSET.find(2)< ms(array, array + sizeof(array) / sizeof(array[0]));
    	cout <<*ms.find(6)<

  2. 映射map、多重映射multimap

     

    map、multimap都位于头文件map中。它们都是按照键排序的,也可以反转。

    map中的键是唯一的,不能存储多个相同值,键、值互相关联,且类型可以不同
    multimap中可以储存多个重复键,键、值互相关联,且类型可以不同。

    · map和multimap共有的成员

    函数 说明
    X::key_type 表示键Key,类型
    X::key_compare 表示键的比较对象Compare,默认为less
    X::value_compare 二元谓词类型,与 set 和 multiset 的 key_compare 相同,为 map 或 multimap 容器中的 pair 值提供了排序功能
    X::mapped_compare 表示值类型,即T

    · map的成员函数
    set的成员函数主要与数学意义上的集合操作相同,具体如下:(i、j为set对象A的区间的迭代器, p、q为对象B的区间的迭代器,objOI是输出迭代器,t为类型T对象,c为用于比较的函数对象,迭代器类型为map::iterator
    函数 说明
    map,Alloc=allocator>> A() 创建键类型为KT、值类型为VT的set对象A,比较对象c默认值为less,分配器Alloc默认为allocator>
    map A(p, q, c) 创建键值类型为T的set对象A,其内容为对象B的区间[p, q)的内容,并使用函数对象c作为比较对象,c默认为less
    A.find(k) 返回一个迭代器,该迭代器指向键与 k 相同的元素;如果没有找到这样的元素,则返回 a.end()。

    map::iterator迭代器实际上指向pair对象,通过first成员访问键,second成员访问值。
    A[k] 返回一个指向与键 k 关联的值的引用(map特有的数组表示法)
    A.lower_bound(k) 返回一个map::iterator类型的迭代器,该迭代器指向第一个键不小于 k 的元素
    A.upper_bound(k) 返回一个迭代器,该迭代器指向第一个键不大于 k 的元素
    A.insert(pair(v,k)) 插入一个键值对为(v,k)的pair对象
    A.insert(p, q) 插入B集合中区间[p,q)的值

    · multimap成员方法
    multimap成员方法如下:
    (i、j为multimap对象A的区间的迭代器, p、q为对象B的区间的迭代器,objOI是输出迭代器,t为类型T对象,c为用于比较的函数对象,迭代器类型为multimap::iterator
    函数 说明
    multimap,
    Alloc=allocator>> A()
    创建键类型为KT、值类型为VT的multimap对象A,比较对象c默认为less函数对象,分配器Alloc默认为allocator
    multimapA(B.begin(), B.end(), c) 创建键值类型为T的set对象A,其内容为对象B的区间[begin, end)的内容,并使用函数对象c作为比较对象,c默认为less
    A.find(k) 返回一个迭代器,该迭代器指向键与 k 相同的元素;如果没有找到这样的元素,则返回 a.end()
    A.lower_bound(k) 返回一个迭代器,该迭代器指向第一个键不小于 k 的元素
    A.upper_bound(k) 返回一个迭代器,该迭代器指向第一个键不大于 k 的元素
    A.insert(pair(v,k)) 插入一个键值对为(v,k)的pair对象
    A.insert(p, q) 插入B集合中区间[p,q)的值

    · map、multimap的使用
    #include
    #include
    using namespace std;
    
    int main()
    {
    	int arrInt[]={12,2,3,5,6};
    	int array[] = { 0, 2, 1, 4, 3, 6, 5, 7, 8, 9, 0, 7, 6};
    	map objmap;
    	multimapobjMTmap;
    	int arrIntSize=sizeof(arrInt)/sizeof(arrInt[0]);
    	for (int i = 0; i (arrInt[i],arrInt[arrIntSize-1-i]));
    	}
    	map::iterator objMapI=objmap.find(3);
        //find()返回迭代器类型为    map::iterator
        //不能使用pair objPair来获得返回值
    	objmap[12];
    	cout<<"The value of key 3 is : "<<(*objMapI).second<

无序关联容器

无序关联容器也是通过键查找值,但其通过哈希表实现,且元素也是无序的,能够快速存取元素。无序关联容器通过哈希函数计算某个对象的索引,索引相同的对象放在一个桶中,进而只在索引对应的桶中搜索。理想情况下,应有足够多的桶,每个桶只包含为数不多的对象。主要有unordered_map、unordered_set、unordered_multimap三种。

  1. 无序关联容器共有的成员
    以下表格中X表示unordered_set、unordered_map、unordered_multimap中任意一种无序关联容器。
    函数 说明
    X::key_type 表示键Key,类型
    X::key_equal 二元谓词binary predicate,用于表示两个类型的Key参数是否相同
    X::hasher Hash函数,用于计算索引值的二元函数对象
    X::local_iterator 实际上是一个类型与 X::iterator 相同的迭代器,但只能用于一个桶(即一个索引)
    X::const_local_iterator 实际上是一个类型与 X::const_iterator 相同的迭代器,但只能用于一个桶(即一个索引)
    X::mapped_type unordered_map 、unordered_multimap中关联数据类型
     
    1. 无序关联容器共有的成员方法

      无序关联容器的成员方法接口与关联容器类似,拥有的方法也相近,但是没有lower_bound()、upper_bound(),因为它是无序的。需要注意的是unordered_map也支持使用[]和索引值访问桶。

      (X表示任意一种无序关联容器类型,n为无序关联容器的桶数,hf为哈希函数,A表示类X的对象,i、j为类X对象A的区间的迭代器, p、q为对象B的区间的迭代器,t为类型T对象,eq为相等谓词迭代器类型为X::iterator
      函数 说明
      X,
      Alloc=allocator>> A()
      创建键类型为KT、值类型为VT的无序关联容器对象A,比较对象c默认为less函数对象,分配器Alloc默认为allocator
      X(n, hf, eq) 创建一个至少包含 n 个桶的匿名空容器,该无序关联容器将 hf 用作哈希函数,将eq用作键值相等谓词。hf默认值为 hasher(), eq默认值为key_equal()。
      X A(n, hf, eq) 创建一个至少包含 n 个桶的空容器A,该无序关联容器将 hf 用作哈希函数,将eq用作键值相等谓词。hf默认值为 hasher(), eq默认值为key_equal()。
      X A(p, q, n, hf, eq) 创建一个至少包含 n 个桶的空容器,将 hf 用作哈希函数,将 eq 用作键值相等谓词,并插入 区间[p, q]中的元素。n省略时桶数不定;hf默认值为 hasher(), eq默认值为key_equal()。
      X A(B.begin(), B.end(), c) 创建键值类型为T的set对象A,其内容为对象B的区间[begin, end)的内容,并使用函数对象c作为比较对象,c默认为less
      A.find(k) 返回一个迭代器,该迭代器指向键与 k 相同的元素;如果没有找到这样的元素,则返回 a.end()
      A.insert(pair(v,k)) 插入一个键值对为(v,k)的pair对象
      A.insert(p, q) 插入B集合中区间[p,q)的值
      A.hash_function() 返回A使用的哈希函数
      A.key_equal() 返回A使用的键值相等谓词
      A.bucket(k) 返回键值为 k 的元素所属桶的索引
      A.bucket_size(index) 返回索引为index的桶的所包含的元素
      A.bucket_count() 返回A包含的桶数
      A.begin(index) 返回一个迭代器,它指向索引为index的桶中的第一个元素
      A.end(index) 返回一个迭代器,它指向索引为index的桶中的最后一个元素
      A.cbegin(index) 返回一个常量迭代器(即const_iterator),它指向索引为index的桶中的第一个元素
      A.cend(index) 返回一个迭代器,它指向索引为index的桶中的最后一个元素
      A.rehash(n) 将桶数调整为不小于 n,并确保A.bucket_count() > A.size() / A.max_load_factor()
  2. 无序关联容器的使用

    与关联容器类似,代码略。

算法

STL中除了容器类的成员方法外,其还含有一些不需要使用容器类对象调用的函数,这些函数主要分为四类:
①非修改式序列操作:面向序列容器的不会修改数据的函数;
②修改式序列操作:面向序列容器的修改数据的函数;
③排序和相关操作
④通用数字运算
前三类放在头文件algorithm,第四类算法放在头文件numeric中。

一般而言,选择容器类的成员方法更加好,因为它更适用于特定容器。

(该部分等使用到了再来补!)

你可能感兴趣的:(C++语言学习整理,c++,开发语言)