zoukankan      html  css  js  c++  java
  • 侯捷STL课程及源码剖析学习1

    1.C++标准库和STL

      C++标准库以header files形式呈现:

    1. C++标准库的header files不带后缀名(.h),例如#include <vector>
    2. 新式C header files 不带后缀名.h,例如#include<cstdio>
    3. 旧式C header files (带有后缀名.h)仍然可用,例如#include <stdio.h>
    4. 新式headers内的组件封装于namespace “std”。     using namespace std;或者以 using std::cout;的形式
    5. 旧式headers 内的组件不封装于namespace "std"

      在标准库中,标准模板库STL(Standard Template Library),占据了标准库70%,80%以上的内容。

    C++ 标准库的范围大于STL的范围。STL的核心思想是泛型编程(Generic Programming)。

    重要资源:

    网站:

    书籍:

    • The C++ standard Library second edition;
    • STL 源码剖析

    2.STL 六大组件

    STL分为六大组件:

    • 容器(container):常用数据结构,大致分为两类,序列容器,如vector,list,deque,关联容器,如set,map。在实现上,是类模板(class template)
    • 迭代器(iterator):一套访问容器的接口,行为类似于指针。它为不同算法提供的相对统一的容器访问方式,使得设计算法时无需关注过多关注数据。(“算法”指广义的算法,操作数据的逻辑代码都可认为是算法)
    • 算法(algorithm):提供一套常用的算法,如sort,search,copy,erase … 在实现上,可以认为是一种函数模板(function template)。
    • 配置器(allocator):为容器提供空间配置和释放,对象构造和析构的服务,也是一个class template。
    • 仿函数(functor):作为函数使用的对象,用于泛化算法中的操作。
    • 配接器(adapter):将一种容器修饰为功能不同的另一种容器,如以容器vector为基础,在其上实现stack,stack的行为也是一种容器。这就是一种配接器。除此之外,还有迭代器配接器和仿函数配接器。

    image

    STL 六大组件的交互关系

    • Container 通过 Allocator 取得数据储存空间
    • Algorithm 通过 Iterator 存取 Container 内容
    • Functor 可以协助 Algorithm 完成不同的策略变化
    • Adapter 可以修饰或套接 FunctorIterator
    #include <vector>
    #include <algorithm>
    #include <functional>
    #include <iostream>
    
    using namespace std;
    
    int main()
    {
        int ia[6] = { 27, 210, 12, 47, 109, 83 };
            vector<int, allocator<int>> vi(ia, ia + 6);
    
        cout << count_if(vi.begin(), vi.end(),
            not1(bind2nd(less<int>(), 40)));
    
        return 0;
    }

    上述这段代码用到了STL的六大部件:

    allocator 是分配器,vector 是容器,count_if 是算法

    vi.begin() 是迭代器

    not1,bind2nd是适配器

    less<int> 是仿函数

    • 理解容器的前闭后开的设计。迭代器类似于指针,很多操作和指针差不多++,--运算。vec.begin(),vec.end()指向容器最后一个元素的下一个位置,解引用*(vec.end())错误!
    • auto关键字的应用

     c++知识点

    临时对象

     1 //临时对象的产生与运用
     2 #include <vector>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 template <typename T>
     8 class print
     9 {
    10 public:
    11   void operator()(const T& elem) // operator()重载
    12   {
    13     cout<<elem<<' ';
    14   }
    15 };
    16 
    17 int main()
    18 {
    19     int ia[6] = {0,1,2,3,4,5};
    20     vector<int> iv(ia, ia+6);
    21 
    22     // print<int>() 是一个临时对象,不是函数调用
    23     for_each(iv.begin(), iv.end(), print<int>());
    24 
    25     cout<<endl;
    26 
    27   return 1;
    28 }
    temp obj

    静态整数成员变量

     1 //静态常量整数初始化
     2 #include <iostream>
     3 using namespace std;
     4 
     5 template <typename T>
     6 class testClass
     7 {
     8 
     9 public:
    10 
    11     static const int _datai = 5;
    12     static const long _datal = 3L;
    13     static const char _datac = 'c';
    14 };
    15 
    16 int main()
    17 {
    18     cout<<testClass<int>::_datai<<endl;
    19     cout<<testClass<long>::_datal<<endl;
    20     cout<<testClass<char>::_datac<<endl;
    21 
    22     return 0;
    23 }
    static constant

    重载自增、自减、操作符

     1 #include <iostream>
     2 using namespace std;
     3 
     4 class INT
     5 {
     6     friend ostream& operator<<(ostream& os, const INT& i);
     7 
     8 public:
     9     INT(int i) : m_i(i) { };
    10 
    11     //  prefix : increment and then fetch
    12     //  ++INT
    13     INT& operator++()
    14     {
    15         ++(this->m_i);
    16         return *this;
    17     }
    18 
    19     //  postfix : fetch and then increment
    20     //  INT++
    21     const INT operator++(int)
    22     {
    23         INT temp = *this;
    24         ++(*this);
    25         return temp;
    26     }
    27 
    28     //  prefix  :   decrement and then fetch
    29     //  --INT
    30     INT& operator--()
    31     {
    32         --(this->m_i);
    33         return *this;
    34     }
    35 
    36     //  prefix  :   fetch and then decrement
    37     const INT operator--(int)
    38     {
    39         INT temp = *this;
    40         --(*this);
    41         return temp;
    42     }
    43 
    44     int& operator*() const
    45     {
    46         return (int&)m_i;
    47     }
    48 
    49 private:
    50     int m_i;
    51 };
    52 
    53 ostream& operator<<(ostream& os, const INT& i)
    54 {
    55     os <<'[' <<i.m_i <<']';
    56     return os;
    57 }
    58 
    59 int main()
    60 {
    61     INT I(5);
    62     cout <<I++ <<endl;
    63     cout <<++I <<endl;
    64     cout <<I-- <<endl;
    65     cout <<--I <<endl;
    66     cout <<*I <<endl;
    67 
    68   return 1;
    69 }
    View Code

    operator() 重载

     1 #include <cstdlib>
     2 #include <iostream>
     3 
     4 using namespace std;
     5 
     6 int fcmp(const void *elem1, const void *elem2);
     7 
     8 int main( )
     9 {
    10     int ia[] = {32, 92, 67, 58, 10, 4, 25, 52, 59, 54};
    11 
    12     for(int i = 0; i < 10; i++)
    13     {
    14         cout <<ia[i] <<" ";
    15     }
    16     cout <<endl;
    17 
    18     qsort(ia, sizeof(ia)/sizeof(ia[0]), sizeof(ia[0]), fcmp);
    19 
    20 
    21     for(int i = 0; i < 10; i++)
    22     {
    23         cout <<ia[i] <<" ";
    24     }
    25     cout <<endl;
    26 
    27 }
    28 
    29 int fcmp(const void *elem1, const void *elem2)
    30 {
    31     const int *i1 = (const int *)elem1;
    32     const int *i2 = (const int *)elem2;
    33 
    34     return (*i1 - *i2);
    35 }
    qsort

    仿函数,函数对象

     1 #include <iostream>
     2 using namespace std;
     3 
     4 //  由于将operator()重载了, 因此plus成了一个仿函数
     5 template <class T>
     6 struct myplus
     7 {
     8     T operator()(const T& x, const T& y) const
     9     {
    10         return x + y;
    11     }
    12 };
    13 
    14 //  由于将operator()重载了, 因此minus成了一个仿函数
    15 
    16 template <class T>
    17 struct myminus
    18 {
    19     T operator()(const T& x, const T& y) const
    20     {
    21         return x - y;
    22     }
    23 };
    24 
    25 int main()
    26 {
    27     //  创建仿函数对象
    28     myplus<int> plusobj;
    29     myminus<int> minusobj;
    30 
    31     cout<<plusobj(3,5)<<endl;
    32     cout<<minusobj(3,5)<<endl;
    33 
    34     cout<<myplus<int>()(43,50)<<endl;
    35     cout<<myminus<int>()(43,50)<<endl;
    36 
    37     return 1;
    38 }
    functor

    3.容器的相关知识

    3.1容器的结构与分类

    容器按在内存中的存储结构分为三种:顺序容器(Sequence Container)、关联容器(Associative Container)、和无序容器(Unordered Container)。其中的无序容器是C++ 11提出的,实际上无序容器也属于关联容器,使用哈希表构成。

    • Array数组容器,大小固定的
    • Deque:两段都可以进行插入删除操作,但是从内存上讲不通,怎么实现的要从后面的学习知道。
    • List:是一个双向的循环链表,注意是双向的。
    • Forward-List:单向链表,当能用单向链表的时候尽量用,可以减少内存空间,一个指针在32位pc上占4个字节,当数据量很多上百万,不可忽略!
    • Set键值都一样,MultiSet允许元素有重复。
    • Set/Map用红黑树实现,RB-tree是自平衡的二叉树。
    • Unorder Containers:是C++标准库里卖的内容。
    • 根据这些图例,可以知道这些容器在内存用到的数据结构是什么样的。
    • HashTable实现方法很多,但基本都用Separate Chaining(分离链地址法实现)。

    容器测试辅助函数 

     1 using std::cin;
     2 using std::cout;
     3 using std::string;
     4 
     5 long get_a_target_long()
     6 {
     7     long target = 0;
     8 
     9     cout << "target (0~" << RAND_MAX << "): ";
    10     cin >> target;
    11     return target;
    12 }
    13 
    14 string get_a_target_string()
    15 {
    16     long target = 0;
    17     char buf[10];
    18 
    19     cout << "target (0~" << RAND_MAX << "): ";
    20     cin >> target;
    21     snprintf(buf, 10, "%d", target);
    22     return string(buf);
    23 }
    24 
    25 int compareLongs(const void* a, const void* b)
    26 {
    27     return (*(long*)a - *(long*)b);
    28 }
    29 
    30 int compareStrings(const void* a, const void* b)
    31 {
    32     if (*(string*)a > *(string*)b)
    33         return 1;
    34     else if (*(string*)a < *(string*)b)
    35         return -1;
    36     else
    37         return 0;
    38 }
    View Code

     注:Windows环境下 应使用函数:_snprintf(buf, 10, "%d", target);

    3.2顺序容器

    顺序容器:它将单一类型元素聚集起来成为容器,然后根据位置来存储和访问这些元素。

    标准库提供了一下几种顺序容器:array、vector、list、forward_list、slist、deque、stack和queue,他们的差别在于访问元素访问元素的方式,以及添加或删除元素相关操作的运行代价。array是C++11的新内容,功能比内置数组更加强大,可以以对象为单位存储数据,vector支持快速随机访问,list支持快速插入/删除,deque是一个双端队列,queue和stack在STL中都是基于deque来实现。

    顺序容器类型

    vector

    • 可变大小数组;
    • 支持快速随机访问;
    • 在尾部之外的位置插入或删除元素可能很慢;       

    deque

    • 双端队列;
    • 支持快速随机访问;
    • 在头尾位置插入/删除速度很快;

    list

    • 双向链表;
    • 只支持双向顺序访问;
    • 在list中任何位置进行插入/删除操作速度都很快;

    forward_list

    • 单向链表;
    • 只支持单向顺序访问;
    • 在链表任何位置进行插入/删除操作速度都很快;

    array

    • 固定大小数组;
    • 支持快速随机访问;
    • 不能添加或删除元素;

    string

    • 与vector相似的容器,但专门用于保存字符;
    • 随机访问快;
    • 在尾部插入/删除速度快;
    • array 测试代码
     1 #include <array>
     2 #include <iostream>
     3 #include <ctime> 
     4 #include <cstdlib> //qsort, bsearch, NULL
     5 #include <cstdio>  
     6 namespace jj01
     7 {
     8     void test_array()
     9     {
    10         cout << "
    test_array().......... 
    ";
    11  
    12         array<long, ASIZE> c;
    13  
    14         clock_t timeStart = clock();
    15         for (long i = 0; i< ASIZE; ++i) {
    16             c[i] = rand();
    17         }
    18         cout << "milli-seconds : " << (clock() - timeStart) << endl;  //
    19         cout << "array.size()= " << c.size() << endl;
    20         cout << "array.front()= " << c.front() << endl;
    21         cout << "array.back()= " << c.back() << endl;
    22         cout << "array.data()= " << c.data() << endl;
    23  
    24         long target = get_a_target_long();
    25  
    26         timeStart = clock();
    27         ::qsort(c.data(), ASIZE, sizeof(long), compareLongs);
    28         long* pItem = (long*)::bsearch(&target, (c.data()), ASIZE, sizeof(long), compareLongs);
    29         cout << "qsort()+bsearch(), milli-seconds : " << (clock() - timeStart) << endl;   //    
    30         if (pItem != NULL)
    31             cout << "found, " << *pItem << endl;
    32         else
    33             cout << "not found! " << endl;
    34     }
    35 }
    array

      注:array 为c++11 新增容器,档测试数据 ASIZE 较大时,在vs2013运行时报出堆栈溢出错误,需要在工程属性中更改堆栈默认大小(默认为1M)。

    测试结果

    test_array()..........
    milli-seconds : 32
    array.size()= 500000
    array.front()= 41
    array.back()= 29794
    array.data()= 0x47970
    target (0~32767): 123
    qsort()+bsearch(), milli-seconds : 263
    found, 123
    View Code
    • vector 测试
     1 #include <vector>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <iostream>
     7 #include <ctime> 
     8 #include <algorithm>     //sort()
     9 namespace jj02
    10 {
    11     void test_vector(long& value)
    12     {
    13         cout << "
    test_vector().......... 
    ";
    14 
    15         vector<string> c;
    16         char buf[10];
    17 
    18         clock_t timeStart = clock();
    19         for (long i = 0; i< value; ++i)
    20         {
    21             try {
    22                 snprintf(buf, 10, "%d", rand());
    23                 c.push_back(string(buf));
    24             }
    25             catch (exception& p) {
    26                 cout << "i=" << i << " " << p.what() << endl;
    27                 //曾经最高 i=58389486 then std::bad_alloc
    28                 abort();
    29             }
    30         }
    31         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    32         cout << "vector.max_size()= " << c.max_size() << endl;    //1073747823
    33         cout << "vector.size()= " << c.size() << endl;
    34         cout << "vector.front()= " << c.front() << endl;
    35         cout << "vector.back()= " << c.back() << endl;
    36         cout << "vector.data()= " << c.data() << endl;
    37         cout << "vector.capacity()= " << c.capacity() << endl << endl;
    38 
    39 
    40         string target = get_a_target_string();
    41         {
    42             timeStart = clock();
    43             auto pItem = find(c.begin(), c.end(), target);
    44             cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    45 
    46             if (pItem != c.end())
    47                 cout << "found, " << *pItem << endl << endl;
    48             else
    49                 cout << "not found! " << endl << endl;
    50         }
    51 
    52         {
    53             timeStart = clock();
    54             sort(c.begin(), c.end());
    55             cout << "sort(), milli-seconds : " << (clock() - timeStart) << endl;
    56 
    57             timeStart = clock();
    58             string* pItem = (string*)::bsearch(&target, (c.data()),
    59                 c.size(), sizeof(string), compareStrings);
    60             cout << "bsearch(), milli-seconds : " << (clock() - timeStart) << endl;
    61 
    62             if (pItem != NULL)
    63                 cout << "found, " << *pItem << endl << endl;
    64             else
    65                 cout << "not found! " << endl << endl;
    66         }
    67 
    68         c.clear();
    69         test_moveable(vector<MyString>(), vector<MyStrNoMove>(), value);
    70     }
    71 }
    vector

     ::find()模板函数,加冒号表明是全局函数,当没有冒号时,编译器在当前没有找到,到全局去找。

    测试结果

    how many elements: 1000000
    
    test_vector()................
    milli-seconds : 750
    vetor.max_size() = 576460752303423487
    vector.size() = 1000000
    vector.front() = 41
    vetor.back() = 12679
    vector.data() = 0x42c0040
    vector.capacity()= 1048576
    
    target (0~32767): 23456
    std::find(),milli-seconds : 5
    find , 23456
    
    sort(), milli-seconds : 6069
    bsearch(), milli-seconds : 1
    found, 23456
    View Code
    • list 测试
     1 #include <list>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <algorithm> //find()
     7 #include <iostream>
     8 #include <ctime> 
     9 namespace jj03
    10 {
    11     void test_list(long& value)
    12     {
    13         cout << "
    test_list().......... 
    ";
    14 
    15         list<string> c;
    16         char buf[10];
    17         
    18         clock_t timeStart = clock();
    19         for (long i = 0; i< value; ++i)
    20         {
    21             try {
    22                 snprintf(buf, 10, "%d", rand());
    23                 c.push_back(string(buf));                
    24             }
    25             catch (exception& p) {
    26                 cout << "i=" << i << " " << p.what() << endl;
    27                 abort();
    28             }
    29         }
    30         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    31         cout << "list.size()= " << c.size() << endl;
    32         cout << "list.max_size()= " << c.max_size() << endl;    //357913941
    33         cout << "list.front()= " << c.front() << endl;
    34         cout << "list.back()= " << c.back() << endl;
    35 
    36         string target = get_a_target_string();
    37         timeStart = clock();
    38         auto pItem = find(c.begin(), c.end(), target);
    39         cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    40 
    41         if (pItem != c.end())
    42             cout << "found, " << *pItem << endl;
    43         else
    44             cout << "not found! " << endl;
    45 
    46         timeStart = clock();
    47         c.sort();
    48         cout << "c.sort(), milli-seconds : " << (clock() - timeStart) << endl;
    49         
    50     }
    51 }
    list

     测试结果

    test_list()..........
    milli-seconds : 496
    list.size()= 1000000
    list.max_size()= 38430716820228232
    list.front()= 21384
    list.back()= 1461
    target (0~32767): 23456
    std::find(), milli-seconds : 1
    found, 23456
    c.sort(), milli-seconds : 4701
    View Code
    • forward_list 测试 
     1 #include <forward_list>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <iostream>
     7 #include <ctime> 
     8 namespace jj04
     9 {
    10     void test_forward_list(long& value)
    11     {
    12         cout << "
    test_forward_list().......... 
    ";
    13 
    14         forward_list<string> c;
    15         char buf[10];
    16 
    17         clock_t timeStart = clock();
    18         for (long i = 0; i< value; ++i)
    19         {
    20             try {
    21                 snprintf(buf, 10, "%d", rand());
    22                 c.push_front(string(buf));
    23             }
    24             catch (exception& p) {
    25                 cout << "i=" << i << " " << p.what() << endl;
    26                 abort();
    27             }
    28         }
    29         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    30         cout << "forward_list.max_size()= " << c.max_size() << endl;  //536870911
    31         cout << "forward_list.front()= " << c.front() << endl;
    32 
    33 
    34         string target = get_a_target_string();
    35         timeStart = clock();
    36         auto pItem = find(c.begin(), c.end(), target);
    37         cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    38 
    39         if (pItem != c.end())
    40             cout << "found, " << *pItem << endl;
    41         else
    42             cout << "not found! " << endl;
    43 
    44         timeStart = clock();
    45         c.sort();
    46         cout << "c.sort(), milli-seconds : " << (clock() - timeStart) << endl;
    47 
    48         c.clear();
    49     }
    50 }
    forward_list

     测试结果

    how many elements: 1000000
    
    test_forward_list()..........
    milli-seconds : 701
    forward_list.max_size()= 461168601842738790
    forward_list.front()= 12679
    target (0~32767): 23456
    std::find(), milli-seconds : 4
    found, 23456
    c.sort(), milli-seconds : 5310
    View Code
    • slist 测试 (非c++标准) 

    Gnu C之前的单链表,forward-list是C++11才出现的

    #include<extslist>头文件

     1 #include <extslist>
     2 //注意, 上一行并没有引发警告讯息如 #include <exthash_set> 所引发者: 
     3 //...4.9.2includec++ackwardackward_warning.h    
     4 //[Warning] ...
     5 
     6 #include <stdexcept>
     7 #include <string>
     8 #include <cstdlib> //abort()
     9 #include <cstdio>  //snprintf()
    10 #include <iostream>
    11 #include <ctime> 
    12 namespace jj10
    13 {
    14     void test_slist(long& value)
    15     {
    16         cout << "
    test_slist().......... 
    ";
    17 
    18         __gnu_cxx::slist<string> c;
    19         char buf[10];
    20 
    21         clock_t timeStart = clock();
    22         for (long i = 0; i< value; ++i)
    23         {
    24             try {
    25                 snprintf(buf, 10, "%d", rand());
    26                 c.push_front(string(buf));
    27             }
    28             catch (exception& p) {
    29                 cout << "i=" << i << " " << p.what() << endl;
    30                 abort();
    31             }
    32         }
    33         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    34     }
    35 }
    slist
    •  deque 测试 
     1 #include <deque>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <iostream>
     7 #include <ctime> 
     8 namespace jj05
     9 {
    10     void test_deque(long& value)
    11     {
    12         cout << "
    test_deque().......... 
    ";
    13 
    14         deque<string> c;
    15         char buf[10];
    16 
    17         clock_t timeStart = clock();
    18         for (long i = 0; i< value; ++i)
    19         {
    20             try {
    21                 snprintf(buf, 10, "%d", rand());
    22                 c.push_back(string(buf));
    23             }
    24             catch (exception& p) {
    25                 cout << "i=" << i << " " << p.what() << endl;
    26                 abort();
    27             }
    28         }
    29         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    30         cout << "deque.size()= " << c.size() << endl;
    31         cout << "deque.front()= " << c.front() << endl;
    32         cout << "deque.back()= " << c.back() << endl;
    33         cout << "deque.max_size()= " << c.max_size() << endl;    //1073741821    
    34 
    35         string target = get_a_target_string();
    36         timeStart = clock();
    37         auto pItem = find(c.begin(), c.end(), target);
    38         cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    39 
    40         if (pItem != c.end())
    41             cout << "found, " << *pItem << endl;
    42         else
    43             cout << "not found! " << endl;
    44 
    45         timeStart = clock();
    46         sort(c.begin(), c.end());
    47         cout << "sort(), milli-seconds : " << (clock() - timeStart) << endl;
    48 
    49         c.clear();
    50         test_moveable(deque<MyString>(), deque<MyStrNoMove>(), value);
    51     }
    52 }
    deque

     测试结果

    how many elements: 100000
    
    test_deque()..........
    milli-seconds : 49
    deque.size()= 100000
    deque.front()= 41
    deque.back()= 1629
    deque.max_size()= 576460752303423487
    target (0~32767): 3456
    std::find(), milli-seconds : 9
    found, 3456
    sort(), milli-seconds : 668
    View Code
    • stack 测试 
     1 #include <stack>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <iostream>
     7 #include <ctime> 
     8 namespace jj17
     9 {
    10     void test_stack(long& value)
    11     {
    12         cout << "
    test_stack().......... 
    ";
    13 
    14         stack<string> c;
    15         char buf[10];
    16 
    17         clock_t timeStart = clock();
    18         for (long i = 0; i< value; ++i)
    19         {
    20             try {
    21                 snprintf(buf, 10, "%d", rand());
    22                 c.push(string(buf));
    23             }
    24             catch (exception& p) {
    25                 cout << "i=" << i << " " << p.what() << endl;
    26                 abort();
    27             }
    28         }
    29         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    30         cout << "stack.size()= " << c.size() << endl;
    31         cout << "stack.top()= " << c.top() << endl;
    32         c.pop();
    33         cout << "stack.size()= " << c.size() << endl;
    34         cout << "stack.top()= " << c.top() << endl;
    35 
    36 
    37         {
    38             stack<string, list<string>> c;        //以 list 为底层 
    39             for (long i = 0; i< 10; ++i) {
    40                 snprintf(buf, 10, "%d", rand());
    41                 c.push(string(buf));
    42             }
    43             cout << "stack.size()= " << c.size() << endl;
    44             cout << "stack.top()= " << c.top() << endl;
    45             c.pop();
    46             cout << "stack.size()= " << c.size() << endl;
    47             cout << "stack.top()= " << c.top() << endl;
    48         }
    49 
    50         {
    51             stack<string, vector<string>> c;    //以 vector 为底层 
    52             for (long i = 0; i< 10; ++i) {
    53                 snprintf(buf, 10, "%d", rand());
    54                 c.push(string(buf));
    55             }
    56             cout << "stack.size()= " << c.size() << endl;
    57             cout << "stack.top()= " << c.top() << endl;
    58             c.pop();
    59             cout << "stack.size()= " << c.size() << endl;
    60             cout << "stack.top()= " << c.top() << endl;
    61         }
    62 
    63         {
    64             stack<string, set<string>> c;    //以 set 为底层 
    65             /*!
    66             for(long i=0; i< 10; ++i) {
    67             snprintf(buf, 10, "%d", rand());
    68             c.push(string(buf));
    69             }
    70             cout << "stack.size()= " << c.size() << endl;
    71             cout << "stack.top()= " << c.top() << endl;
    72             c.pop();
    73             cout << "stack.size()= " << c.size() << endl;
    74             cout << "stack.top()= " << c.top() << endl;
    75 
    76             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
    77             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'back'
    78             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_back'
    79             */
    80         }
    81 
    82         //!stack<string, map(string>> c5;    ////以 map 为底层, [Error] template argument 2 is invalid
    83         //!stack<string>::iterator ite1;      //[Error] 'iterator' is not a member of 'std::stack<std::basic_string<char> >'
    84 
    85     }
    86 }
    stack
    •  queue 测试 
     1 #include <queue>
     2 #include <stdexcept>
     3 #include <string>
     4 #include <cstdlib> //abort()
     5 #include <cstdio>  //snprintf()
     6 #include <iostream>
     7 #include <ctime> 
     8 namespace jj18
     9 {
    10     void test_queue(long& value)
    11     {
    12         cout << "
    test_queue().......... 
    ";
    13 
    14         queue<string> c;
    15         char buf[10];
    16 
    17         clock_t timeStart = clock();
    18         for (long i = 0; i< value; ++i)
    19         {
    20             try {
    21                 snprintf(buf, 10, "%d", rand());
    22                 c.push(string(buf));
    23             }
    24             catch (exception& p) {
    25                 cout << "i=" << i << " " << p.what() << endl;
    26                 abort();
    27             }
    28         }
    29         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    30         cout << "queue.size()= " << c.size() << endl;
    31         cout << "queue.front()= " << c.front() << endl;
    32         cout << "queue.back()= " << c.back() << endl;
    33         c.pop();
    34         cout << "queue.size()= " << c.size() << endl;
    35         cout << "queue.front()= " << c.front() << endl;
    36         cout << "queue.back()= " << c.back() << endl;
    37 
    38 
    39         {
    40             queue<string, list<string>> c;        //以 list 为底层 
    41             for (long i = 0; i< 10; ++i) {
    42                 snprintf(buf, 10, "%d", rand());
    43                 c.push(string(buf));
    44             }
    45             cout << "queue.size()= " << c.size() << endl;
    46             cout << "queue.front()= " << c.front() << endl;
    47             cout << "queue.back()= " << c.back() << endl;
    48             c.pop();
    49             cout << "queue.size()= " << c.size() << endl;
    50             cout << "queue.front()= " << c.front() << endl;
    51             cout << "queue.back()= " << c.back() << endl;
    52         }
    53 
    54         {
    55             queue<string, vector<string>> c;    //以 vector 为底层 
    56             for (long i = 0; i< 10; ++i) {
    57                 snprintf(buf, 10, "%d", rand());
    58                 c.push(string(buf));
    59             }
    60             cout << "queue.size()= " << c.size() << endl;
    61             cout << "queue.front()= " << c.front() << endl;
    62             cout << "queue.back()= " << c.back() << endl;
    63             //!c.pop();  //[Error] 'class std::vector<std::basic_string<char> >' has no member named 'pop_front'
    64             cout << "queue.size()= " << c.size() << endl;
    65             cout << "queue.front()= " << c.front() << endl;
    66             cout << "queue.back()= " << c.back() << endl;
    67         }
    68 
    69         {
    70             queue<string, set<string>> c;        //以 set 为底层 
    71             /*!
    72             for(long i=0; i< 10; ++i) {
    73             snprintf(buf, 10, "%d", rand());
    74             c.push(string(buf));
    75             }
    76             cout << "queue.size()= " << c.size() << endl;
    77             cout << "queue.front()= " << c.front() << endl;
    78             cout << "queue.back()= " << c.back() << endl;
    79             c.pop();
    80             cout << "queue.size()= " << c.size() << endl;
    81             cout << "queue.front()= " << c.front() << endl;
    82             cout << "queue.back()= " << c.back() << endl;
    83             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'push_back'
    84             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'front'
    85             //[Error] 'class std::set<std::basic_string<char> >' has no member named 'pop_front'
    86             */
    87         }
    88 
    89         //! queue<string, map<string>> c5;    //以 map 为底层, [Error] template argument 2 is invalid
    90         //! queue<string>::iterator ite1;      //[Error] 'iterator' is not a member of 'std::queue<std::basic_string<char> >'    
    91     }
    92 }
    queue

    3.3关联容器

      在STL中关联容器使用红黑树来实现,因为不是顺序结构,因而不能使用上面提到的push和pop函数,使用insert和erase函数来实现元素的插入删除操作。

      关联容器支持通过键来高效地查找和读取元素,两个基本的关联容器类型是map和set。map的元素以键-值(key-value)对的形式组织:键用于元素在map中的索引,而值则表示所存储和读取的数据。set仅包含一个键,并有效地支持关于某个键是否存在的查询。map可理解为字典,set可理解为一类元素的集合。

    关联容器和顺序容器的本质差别在于:关联容器通过键(key)存储和读取元素,而顺序容器则通过元素在容器中的位置顺序存储和访问元素。

    set 和 map 类型的对象所包含的元素都具有不同的键,不允许为同一个键添加第二个元素。如果一个键必须对应多个实例,则需使用 multimap 或 multiset,这两种类型允许多个元素拥有相同的键。

    • multiset ,set测试 
     1 void test_multiset(long& value)
     2     {
     3         cout << "
    test_multiset().......... 
    ";
     4 
     5         multiset<string> c;
     6         char buf[10];
     7         clock_t timeStart = clock();
     8         for (long i = 0; i< value; ++i)
     9         {
    10             try {
    11                 snprintf(buf, 10, "%d", rand());
    12                 c.insert(string(buf));
    13             }
    14             catch (exception& p) {
    15                 cout << "i=" << i << " " << p.what() << endl;
    16                 abort();
    17             }
    18         }
    19         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    20         cout << "multiset.size()= " << c.size() << endl;
    21         cout << "multiset.max_size()= " << c.max_size() << endl;    //214748364
    22 
    23         string target = get_a_target_string();
    24         {
    25             timeStart = clock();
    26             auto pItem = find(c.begin(), c.end(), target);    //比 c.find(...) 慢很多
    27             cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    28             if (pItem != c.end())
    29                 cout << "found, " << *pItem << endl;
    30             else
    31                 cout << "not found! " << endl;
    32         }
    33 
    34         {
    35             timeStart = clock();
    36             auto pItem = c.find(target);        //比 std::find(...) 快很多
    37             cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
    38             if (pItem != c.end())
    39                 cout << "found, " << *pItem << endl;
    40             else
    41                 cout << "not found! " << endl;
    42         }
    43 
    44 //        c.clear();
    45 //        test_moveable(multiset<MyString>(), multiset<MyStrNoMove>(), value);
    46     }
    47 
    48 void test_set(long& value)
    49     {
    50         cout << "
    test_set().......... 
    ";
    51 
    52         set<string> c;
    53         char buf[10];
    54 
    55         clock_t timeStart = clock();
    56         for (long i = 0; i< value; ++i)
    57         {
    58             try {
    59                 snprintf(buf, 10, "%d", rand());
    60                 c.insert(string(buf));
    61             }
    62             catch (exception& p) {
    63                 cout << "i=" << i << " " << p.what() << endl;
    64                 abort();
    65             }
    66         }
    67         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    68         cout << "set.size()= " << c.size() << endl;
    69         cout << "set.max_size()= " << c.max_size() << endl;       //214748364
    70 
    71         string target = get_a_target_string();
    72         {
    73             timeStart = clock();
    74             auto pItem = find(c.begin(), c.end(), target);    //比 c.find(...) 慢很多
    75             cout << "std::find(), milli-seconds : " << (clock() - timeStart) << endl;
    76             if (pItem != c.end())
    77                 cout << "found, " << *pItem << endl;
    78             else
    79                 cout << "not found! " << endl;
    80         }
    81 
    82         {
    83             timeStart = clock();
    84             auto pItem = c.find(target);        //比 std::find(...) 快很多
    85             cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
    86             if (pItem != c.end())
    87                 cout << "found, " << *pItem << endl;
    88             else
    89                 cout << "not found! " << endl;
    90         }
    91     }
    set
    • multimap,map 测试 
     1 void test_unordered_map(long& value)
     2     {
     3         cout << "
    test_unordered_map().......... 
    ";
     4 
     5         unordered_map<long, string> c;
     6         char buf[10];
     7 
     8         clock_t timeStart = clock();
     9         for (long i = 0; i< value; ++i)
    10         {
    11             try {
    12                 snprintf(buf, 10, "%d", rand());
    13                 c[i] = string(buf);
    14             }
    15             catch (exception& p) {
    16                 cout << "i=" << i << " " << p.what() << endl;
    17                 abort();
    18             }
    19         }
    20         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    21         cout << "unordered_map.size()= " << c.size() << endl;    //357913941
    22         cout << "unordered_map.max_size()= " << c.max_size() << endl;
    23 
    24         long target = get_a_target_long();
    25         timeStart = clock();
    26         //! auto pItem = find(c.begin(), c.end(), target);    //map 不适用 std::find()
    27         auto pItem = c.find(target);
    28 
    29         cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
    30         if (pItem != c.end())
    31             cout << "found, value=" << (*pItem).second << endl;
    32         else
    33             cout << "not found! " << endl;
    34     }
    35 
    36 void test_map(long& value)
    37     {
    38         cout << "
    test_map().......... 
    ";
    39 
    40         map<long, string> c;
    41         char buf[10];
    42 
    43         clock_t timeStart = clock();
    44         for (long i = 0; i< value; ++i)
    45         {
    46             try {
    47                 snprintf(buf, 10, "%d", rand());
    48                 c[i] = string(buf);
    49             }
    50             catch (exception& p) {
    51                 cout << "i=" << i << " " << p.what() << endl;
    52                 abort();
    53             }
    54         }
    55         cout << "milli-seconds : " << (clock() - timeStart) << endl;
    56         cout << "map.size()= " << c.size() << endl;
    57         cout << "map.max_size()= " << c.max_size() << endl;        //178956970
    58 
    59         long target = get_a_target_long();
    60         timeStart = clock();
    61         auto pItem = c.find(target);
    62         cout << "c.find(), milli-seconds : " << (clock() - timeStart) << endl;
    63         if (pItem != c.end())
    64             cout << "found, value=" << (*pItem).second << endl;
    65         else
    66             cout << "not found! " << endl;
    67 
    68         c.clear();
    69     }
    map

    3.4无序容器

      严格意义上讲,无序容器也属于关联容器。

    unordered_set,unordered_map,unordered_multiset,unordered_multimap

  • 相关阅读:
    根据坐标点画图形
    js 解析geojson格式
    devexpress 安装
    DataTable 获取列名
    ADO.NET 注册
    css:outline
    javascript函数sort
    引用类型-2015/10/06
    2015-11-02-js
    jquery
  • 原文地址:https://www.cnblogs.com/flysong/p/8053845.html
Copyright © 2011-2022 走看看