zoukankan      html  css  js  c++  java
  • STL组件概述

    一、六大组件
    容器、类属算法、迭代器、函数对象、适配器、分配器

    二、容器(存储其他对象集合的对象)
    1.序列容器(将一组具有相同类型的对象以严格线性的形式组织在一起)
    • vector<T>:随机访问编程序列,即:访问复杂度为O(1),对序列末尾的插入和删除均是分摊常量;(数组表示
    • deque<T>:随机访问边长序列,对序列开头和末尾的插入和删除操作均是分摊常量的;(两级数组结构实现
    • list<T>:(双向链表)对变长序列的线性时间访问;对序列中任意位置的插入和删除操作时间复杂度为O(1);(双向链表实现
    :(1)对于string类和STL序列容器类,其end成员函数返回的是终点之后的迭代器,而不是真正指向序列最后一个元素的迭代器;
    (2)STL为所有容器类都定义了==运算符;

    2.有序关联容器(有从基于键的集合中快速提取对象的能力,集合的大小可运行时改变)
    • set<Key>:支持唯一的键(每个键只出现一次),并可快速检索键;
    • multi<Key>:支持可重复的键(同一个键可出现多次),可快速检索键key 
    • map<Key,T>:键值对,支持唯一的键可通过键快速检索其对应的类型为T的值;(用find(Key)数据成员实现)
    • multimap<Key,T>:键值对,支持可重复的键;可通过键快速检索其对应的类型为T的值;
    例,向map中插入元素:
    map<string , long> map_test;
    map_test["cyj"]=123;

    注意:STL容器和其他C++容器类库的重要区别之一:STL容器类并没有为其所含的数据提供过多的操作,而是提供了类属算法

    三、类属算法
    1.类属查找算法(适用于任何STL容器)
    • find(iterator1 , iterator2, search_content):若找到,返回第一个出现search_content的位置,否则返回容器某位元素后面一个元素的迭代器;
      例:
      vector<char> vec1 = make<vector<char> >("C++");
      find(vec1.begin|(),vec1.end(),'C');
    注:与表(list)对应的迭代器不支持+运算符,支持自增预算符++;所有STL容器均支持自增预算符++

    2.类属合并算法(merge,将两个序列内的元素合并到一个序列中)
    • 调用形式
      merge(  first1 , last1 , first2 , last2, result );
      (1) 迭代器first1和last1表示一个输入序列的起始和终止位置,元素类型为T;
      (2)迭代器first2和last2表示另一个输入序列的起始和终止位置,元素类型为T;

      (3)两个输入序列均为升序排列

      (4)result表示合并序列存放的起始位置注意:结果容器所有元素均升序排列;若前面两个容器中元素均未升序排列,合并后的result容器非升序排列;三个容器不一定是同一类容器,可以属于不同类别,如:分别为list,char[] , deque容器,但元素类型必须为T;
    例子:
    #include <cassert>
    2 #include <iostream>
    3 #include <deque>
    4 #include <list>
    5 #include <algorithm>
    6 #include "string.h"
    7 #include "stdlib.h"
    8 using namespace std;

    10 template<typename container>
    11 container make( const char source[]);
    12 
    13 int main()
    14 {
    15 char s[]="acd";(升序)
    16 int len = strlen(s);
    17 list<char> list1 = make< list<char> >("befghijklmnopqrstuvwxy");(升序)
    18 deque<char> d(26,'x');
    19 
    20 merge(&s[0],&s[len] , list1.begin() , list1.end(),d.begin());
    assert( d == make< deque<char> >("abcdefghijklmnopqrstuvwxyx"));
    23 std::cout<<"result ok"<<std::endl;
    24 return 0;
    25 }
    26 
    27 
    28 template<typename container>
    29 container make( const char source[])
    30 {
    31 return container( &source[0] , &source[strlen(source)]);
    32 }


    四 迭代器(具有和指针类似的特征)


    1.迭代器分类
    • 输入迭代器:支持!=,*,++,==,但是对于*操作,只能从容器中读取数据,而不能向其中写入数据
    • 输出迭代器:支持!=,*,++,==,但是对于*操作,不能从容器中读取数据,只能向其中写入数据
    • 前向迭代器:支持==,!= , *,++操作;
    • 双向迭代器:支持==,!= , *,++,--操作;
    • 随机访问迭代器:支持==,!= , *,++,--,+=,-=,+,-,<,>,<=,>=操作
    • 类属函数accumulate:accumulate(first,last,init),把init和从first到last指向的值进行累加并返回累加得到的和;
    注意:accumulate、find、merge等一些用于输入地带器的算法比对迭代器有更高要求的算法(如sort算法要求使用随机访问迭代器)通用性强。


    五、函数对象
    • 函数对象:一个实体,可以不带参数,也可以带有一个以上的参数,并能够从中获得一个值或改变程序的状态,除了普通函数,另一类函数对象可以是类或结构的对象,且在其定义中重载了函数调用运算符
    例子:
    #include <iostream>
    2 #include <vector>
    3 #include <algorithm>
    4 #include <numeric> //for accumulate

    6 using namespace std;
    7
    //函数对象,重载函数调用运算符。
    8 class multi{
    9 public:
    10 //function call overload
    11 int operator()(int x , int y ) const
    12 {
    13 return x*y;
    14 }
    15 };
    16 
    17 int main()
    18 {
    19 int x[5]={1,2,3,4,5};
    20 vector<int> vec1(&x[0],&x[5]);
    //1 is inited value
    22 int result = accumulate(vec1.begin() , vec1.end() , 1, multi());
    23 std::cout<<"result is:"<<result<<std::endl;
    24 }

    • 在类multi中定义函数调用运算符operator(),就定义了一种可以作为函数参数的对象,可以像使用函数一样使用该对象;multi()使用编译器提供的默认构造函数;该对象没有响应的内存,只有函数定义;
    • 函数对象的优势
      (1)以类的形式定义函数对象,可以携带更多额外信息,某些类属算法或容器将会用到这类信息;
      (2)更加通用、高效

    六、适配器(改变其他组件接口的组件)
    • 适配器reverse_iterator:将某种类型的迭代器变成一种新的迭代器,但保持其功能不变,将其遍历的方向翻转过来。(使用场景:如用find函数查找某个元素在容器中最后出现的位置;浮点数累加,若元素升序排列,舍入误差通常会小一些,否则,以降序顺序排列时,与累加和相比,非常小的数值对于累加和几乎不起任何作用,因此可用reverse_iterator和accumulate实现降序序列浮点数累加,结果精确些)
    • 注:STL每种容器都定义了reverse_iterator,以及返回这种类型迭代器的rbegin和rend成员函数
    • 栈适配器:将序列容器变换到先进后出的栈接口中;
    • 队列适配器:将序列容器变换到先入先出队列中;
    • 优先级队列:将序列容器变换到优先级队列中,由一个比较参数来控制元素访问顺序。
    • 函数适配器:
      (1)取反器(negator):对判定函数对象(返回值为bool类型)的结果进行取反;
      (2)绑定器(binder):将二元函数的一个参数与某个特定的值绑定,从而将二元函数编程一元函数。
      (3)函数指针适配器:从函数指针得到函数对象。

    七、分配器(封装程序所用的内存分配模式信息)
    注:分配器类可以封装许多信息:指针、常量指针、引用、常量引用、对象大小、不同类型指针之间的差别、分配函数与释放函数以及其他一些函数信息。分配器上所有操作都具有分摊常量的运行时间
  • 相关阅读:
    Traefik使用
    kubernetes nfs-client-provisioner外部存储控制器
    基于腾讯云CLB实现K8S v1.10.1集群高可用+负载均衡
    k8s-rabbitmq-(一)集群部署
    TabSet 实现拖动后并保存配置
    C# MD5加密
    VSS “vc6.0vssum.dat may be corrupt”错误
    C#编程基础笔记
    android.view.WindowLeaked的解决办法
    【转】java线程系列---Runnable和Thread的区别
  • 原文地址:https://www.cnblogs.com/cyjsegull/p/4526300.html
Copyright © 2011-2022 走看看