• 《C++新经典》第19章 STL标准模板库大局观


    19.1 STL总述、发展史、组成与数据结构谈

    19.1.1 几个概念与推荐书籍

    1. C++标准库
      C++ Standard Library,一般安装C++编译器时都会安装。

    2. 标准模板库
      Standard Template Library(STL),包含在C++标准库中(核心)。

    3. 泛型编程
      Generic Programming,使用模板(Template)为主要编程手段来编写代码。

    标准模板库就是用泛型编程的编码方式写的一套供程序员非常方便使用的库。

    1. 推荐书籍
      《C++标准库》、《STL源码剖析》。

    19.1.2 算法和数据结构谈

    1. 数据结构浅谈
      数据结构,研究数据存取的学问。栈、队列、链表、散列表(哈希表)、树、图等,存取速度快慢,优劣势,具体使用场景等。

    2. 数据结构学习方法
      (1)栈:后进先出。
      (2)队列:先进先出。
      (3)链表:多个节点链(串)在一起,每个节点都有数据部分和next指针部分。
      (4)其它树、图、散列表等。

    3. 推荐书籍
      《算法导论》

    19.1.4 标准库使用

    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    19.1.5 STL的组成部分

    1. 容器
      vetcor、map、list等。

    2. 迭代器
      用于遍历或者访问容器中的元素,类似指针。

    3. 算法(函数)
      STL提供的一些函数,用来实现一些功能,例如search(查找)、sort(排序)、copy(复制)等。

    4. 分配器
      不太常用,针对频繁分配小块内存时,减少内存空间的浪费,具有一定的提升分配内存效率的作用(内存分配器)。一般使用默认分配器(allocator)。

    5. 其它
      适配器、仿函数(函数对象)等。

    19.2 容器分类与array、vector容器精解

    19.2.1 容器的分类

    容器,保存数据,用于管理一大群元素。

    1. 顺序容器
      Sequence Containers,array、vector、deque、queue、stack、list、forward_list。

    2. 关联容器
      Associative Containers,每一个元素都是一个键值(key/value)对。通过键来找元素,类似小数据库或小字典,查找快速。内部使用树的数据结构来存储数据,按照一定规则(比如根据key)自动存放元素位置,无法控制元素插入位置,只能控制插入内容。set、multiset、map、multimap。
      hash_set、hash_multiset、hash_map、hash_multimap等(已过时,用unordered_set、unordered_multiset、unordered_map、unordered_multimap替代)。

    3. 无序容器
      Unordered Contianers,属于关联容器的一种,只在意元素是否在容器内,内部用哈希表实现。
      unordered_set、unordered_multiset、unordered_map、unordered_multimap等。

    19.2.2 容器的说明和简单应用

    1. array
      顺序容器,数组,空间连续,大小固定。

    与内置数组比较:
    (1)比内置数组更安全,内置数组不能直接使用拷贝和赋值,array数组可以。
    (2)array下标必须是无符号类型,而数组则没有这个限制(可以负数)。

    array<int, 10> ial1={0,1,2,3};
    array<int, 10> copy=ial1;//只要保证两者的类型一致就可以(包括元素类型和大小)
    
    • 1
    • 2
    #include 
    
    array<string, 5> mystring = {"I", "love", "china"};
    cout <<mystring.size()<<endl;//5
    cout <<sizeof(mystring)<<endl;//不等于5,array类的大小
    mystring[0] = "long long long";
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. vector
      空间连续,动态大小,超过容量时,重新分配空间。
      建议vector内使用指针,或者提前分配空间。
    #include 
    #include 
    using namespace std;
    
    class A
    {
    public:
        int m_i;
        A(int tmp = 0) : m_i(tmp)
        {
            cout << "A(int)\n";
        }
        A(const A &a)
        {
            m_i = a.m_i;
            cout << "A(const A&) \n";
        }
        ~A()
        {
            cout << "~A()\n";
        }
    };
    
    #define N 3
    int main()
    {
        {
            //vector veca(N);
            vector<A> veca;
            veca.reverse(N);
            for (int i = 0; i < N; i++)
            {
                cout << "size=" << veca.size() << endl;
                cout << "capacity=" << veca.capacity() << endl;
                // veca.push_back(A(1));//未提前分配空间,会多次调用构造函数和析构函数
                // veca.emplace_back(A(1));//就地在尾部插入类,省去了拷贝或移动元素的过程。
                veca[i] = A(i);
            }
        }
        cout << "over";
        return 0;
    }
    

    19.3 容器的说明和简单应用续

    19.3.1 deque和stack

    1. deque
      double-ended queue,双端队列(双向开口)。
      分段数组,内存是分段连续的。
    #include 
    #include 
    using namespace std;
    
    class A
    {
    public:
        A(int tmp) : m_i(tmp)
        {
            cout << "A(int)" << endl;
        }
        A(const A &tmpA)
        {
            m_i = tmpA.m_i;
            cout << "A(const A&)" << endl;
        }
        ~A()
        {
            cout << "~A()" << endl;
        }
    
    public:
        int m_i;
    };
    
    int main()
    {
        {
            deque<A> mydeque;
            for (int i = 0; i < 2; i++)
            {
                cout << "begin" << endl;
                mydeque.push_front(A(i));
                mydeque.push_back(A(i));
                cout << "end" << endl;
            }
            for (int i = 0; i < mydeque.size(); i++)
            {
                cout << i << ": " << mydeque[i].m_i << ", address: " << &mydeque[i] << endl;
            }
        }
    
        cout << "main over" << endl;
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    1. stack
      栈或堆栈。
      一端开口,后进先出。

    19.3.2 queue

    队列,先进先出,一端进,一端出。

    19.3.3 list

    双向链表,内存空间不连续。

    沿链查找元素,查找效率不突出;任意位置插入和删除元素都非常迅速。

    19.3.4 其它

    1. forward_list
      单向链表,push_front,头部插入数据。无push_back。

    2. map和set
      关联容器,内部实现多为红黑树。
      map容器,每个元素都是键值对(key/value),key不能重复,重复需使用multimap。

    #include 
    #include 
    #include 
    using namespace std;
    
    class A
    {
    public:
        int m_i;
        A(int tmp = 0) : m_i(tmp)
        {
            cout << "A(int)\n";
        }
        A(const A &a)
        {
            m_i = a.m_i;
            cout << "A(const A&) \n";
        }
        ~A()
        {
            cout << "~A()\n";
        }
    };
    
    #define N 3
    int main()
    {
        map<int, string> mymap = {
            pair<int, string>(1, "java"),
            pair<int, string>(2, "c++"),
            {3, "python"},
            make_pair(4, "go")};
        cout << mymap[4] << endl;
    
        mymap.insert({4, "matlab"}); // key,4存在,这行不执行
        cout << mymap.at(4) << endl;
    
        mymap[4] = "matlab"; // key,4存在,会被替换
        cout << mymap.at(4) << endl;
    
        mymap[5] = "ruby"; // key,5不存在,会赋值
        cout << mymap.at(5) << endl;
    
        cout << mymap.size() << endl;
        cout << mymap[6] << endl;     //生成一个{6, ""}
        cout << mymap.size() << endl; //+1
    
        auto iter = mymap.find(3);
        if (iter != mymap.end())
        {
            cout << iter->first << endl;
            cout << iter->second << endl;
        }
    
        cout << "over";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57

    set容器中,每个元素都是value,value不能重复,重复需使用multiset。

    map、set等关联容器,插入速度慢一些(寻找合适位置),查找速度快。

    1. unordered_map、unordered_set等
      unordered_开头容器属于无序容器,内部一般使用哈希表(散列表)实现。
      unordered_map、unordered_set不重复,unordered_multimap、unordered_multiset可重复。
    #include 
    #include 
    #include 
    using namespace std;
    
    int main()
    {
        unordered_set<int> myset;
        cout << myset.bucket_count() << endl;
    
        for (int i = 0; i < 8; i++)
            myset.insert(i);
        cout << myset.bucket_count() << endl;
    
        cout << myset.max_bucket_count() << endl;
        cout << myset.size() << endl;
    
        for (int i = 0; i < myset.bucket_count(); i++)
            cout << myset.bucket_size(i) << endl;
    
        if (myset.find(5) != myset.end())
            cout << "find\n";
    
        if (find(myset.begin(), myset.end(), 5) != myset.end())
            cout << "find\n";
    
        cout << "over";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    19.4 分配器简介、使用与工作原理说

    19.4.1 分配器简介

    vector<int> myvec;
    vector<int, std::allocator<int>> myvec;
    
    • 1
    • 2

    内存分配器扮演着内存池的角色,大量减少对malloc的调用以减少对内存分配的浪费。

    list<int> mylist;
    mylist.push_back(10);
    mylist.push_back(20);
    mylist.push_back(36);
    for(auto iter = mylist.begin(); iter != mylist.end(); ++iter){
    	cout<<*iter<<endl;
    	int *p=&(*iter);
    	printf("%p\n", p);
    }
    //测试表明,默认分配器未使用内存池工作机制,原样调用底层malloc。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    19.4.2 分配器的使用

    分配器分配内存,写入数据,释放内存。

    allocator<int> aalloc;
    int *p=aalloc.allocate(3);
    int *q=p;
    *q=1;q++;
    *q=2;q++;
    *q=3;
    aalloc.deallocate(p, 3);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    19.4.3 其它的分配器与原理说

    分配器就是一次分配一大块内存,每次使用一小块,用链表将这些内存块管理起来。通过内存池的内存分配机制,有效减少调用malloc次数,减少内存浪费,提高程序运行效率。

    //分配器上不同编号对应不同大小的内存块,
    //应对不同大小的内存分配申请
    //3个list可能共用一个分配器
    list<int, allocator<int>> mylist1;
    list<double, allocator<double>> mylist2;
    list<int, allocator<int>> mylist3;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    19.5 迭代器的概念和分类

    19.5.1 迭代器基本概念

    可遍历STL容器全部或部分元素的对象(行为类似于指针对象,*iter获取迭代器所指向的内容)。
    迭代器由容器提供(容器里面定义者迭代器的具体类型细节),用来表现容器中的某一个位置。

    #include 
    #include 
    using namespace std;
    
    int main()
    {
        vector<int> iv = {1, 2, 3};
        for (vector<int>::iterator iter = iv.begin(); iter != iv.end(); ++iter)
        {
            *iter += 6;
            cout << *iter << endl;
        }
    
        cout << "over";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    19.5.2 迭代器的分类

    依据迭代器的移动特性和操作进行分类。
    (1)输出型迭代器(Output iterator)
    struct output_iterator_tag
    (2)输入型迭代器(Input iterator)
    struct input_iterator_tag
    (3)前向型迭代器(Input iterator)
    struct forward_iterator_tag
    (4)双向迭代器(Bidirectional iterator)
    struct bidirectional_iterator_tag
    (5)随机访问迭代器(Random-access iterator)
    struct random_access_iterator_tag

    struct output_iterator_tag

    继承关系:
    struct input_iterator_tag

    struct forward_iterator_tag

    struct bidirectional_iterator_tag

    struct random_access_iterator_tag

    多数容器有迭代器,stack、queue等容器不提供迭代器。

    迭代器种类迭代器能力提供该迭代器的容器
    output_iterator_tag向前写入ostream
    input_iterator_tag向前读取一次istream
    forward_iterator_tag向前读取forward_list、nordered
    bidirectional_iterator_tag向前和向后读取list、set、multiset、map、multimap
    random_access_iterator_tag随机读取(跳过一定个数的元素)array、vector、deque、string、C风格数组
    #include 
    #include 
    #include 
    #include 
    #include 
    #include 
    using namespace std;
    
    void _display_category(output_iterator_tag mytag)
    {
        cout << "output_iterator_tag" << endl;
    }
    void _display_category(input_iterator_tag mytag)
    {
        cout << "input_iterator_tag" << endl;
    }
    void _display_category(forward_iterator_tag mytag)
    {
        cout << "forward_iterator_tag" << endl;
    }
    void _display_category(bidirectional_iterator_tag mytag)
    {
        cout << "bidirectional_iterator_tag" << endl;
    }
    void _display_category(random_access_iterator_tag mytag)
    {
        cout << "random_access_iterator_tag" << endl;
    }
    
    template <typename T>
    void display_category(T iter)
    {
        cout << "begin" << endl;
    
        typename iterator_traits<T>::iterator_category cagy; //过滤器(萃取机),获取T迭代器类型的种类
        _display_category(cagy);
        cout << "typeid(iter).name()=" << typeid(iter).name() << endl;
    
        cout << "end" << endl;
    }
    
    int main()
    {
        display_category(array<int, 100>::iterator()); //()用于产生临时对象
        display_category(vector<int>::iterator());
        display_category(list<int>::iterator());
        display_category(map<int, int>::iterator());
        display_category(set<int>::iterator());
    
        cout << "over";
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52

    迭代器功能整理:
    (1)输出型迭代器(Output iterator)
    struct output_iterator_tag
    一步步往前走,通过这个迭代器往容器中写数据。
    *iter = value,value写入迭代器指向的位置。
    ++iter
    iter++

    (2)输入型迭代器(Input iterator)
    struct input_iterator_tag
    一步步往前走,通过这个迭代器顺序返回元素值。
    *iter,读取元素值
    iter->member,读取元素成员
    ++iter
    iter++
    iter1 == iter2
    iter1 != iter2

    (3)前向型迭代器(Input iterator)
    struct forward_iterator_tag
    继承input_iterator_tag,同时支持写入操作
    *iter,读取元素值
    iter->member,读取元素成员
    *iter = value,value写入迭代器指向的位置。
    ++iter
    iter++
    iter1 == iter2
    iter1 != iter2
    iter1 = iter2,迭代器赋值

    (4)双向迭代器(Bidirectional iterator)
    struct bidirectional_iterator_tag
    继承forward_iterator_tag,增加向回(反向)迭代,即迭代位置可以往回退。
    *iter,读取元素值
    iter->member,读取元素成员
    *iter = value,value写入迭代器指向的位置。
    ++iter
    iter++
    iter1 == iter2
    iter1 != iter2
    –iter
    iter–

    (5)随机访问迭代器(Random-access iterator)
    struct random_access_iterator_tag
    继承bidirectional_iterator_tag,增加随机访问能力,即增减偏移量,同时能够计算距离,支持一些关系运算等。
    *iter,读取元素值
    iter->member,读取元素成员
    *iter = value,value写入迭代器指向的位置。
    ++iter
    iter++
    iter1 == iter2
    iter1 != iter2
    –iter
    iter–

    iter[n]
    iter+=n
    iter-=n
    iter+n
    iter-n
    iter1-iter2,计算距离
    iter1iter2
    iter1<=iter2, iter1>=iter2

    19.6 算法简介、内部处理与使用范例

    19.6.1 算法简介

    19.6.2 算法内部一些处理

    算法是函数模板,接收各种类型的迭代器作为形参。算法内部根据迭代器类型,有不同处理,处于算法执行效率的考虑。

    19.6.3 一些典型算法使用范例

    #include 
    
    • 1
    1. for_each
    void func(int i){
    	cout<<i<<endl;
    }
    
    vector<int> myvector = {10, 20, 30, 40, 50};
    //两个形参迭代器,一个可调用对象,
    //不断迭代两个迭代器间的元素,作为实参来调用myfunc函数。
    for_each(myvector.begin(), myvector.end(), func);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    template<class InputIterator, class Function>
    Function for_each(InputIterator first, InputIterator last, Function f){
    	for(; first != last; ++first)
    		f(*first);
    	return f;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. find
    vector<int> myvector = {10, 20, 30, 40, 50};
    vector<int>::iterator finditer = find(myvector.begin(), myvector.end(), 400);
    if(finditer != myvector.end())
    	cout<<"find"<<endl;
    else
    	cout<<"not find"<<endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    //优先使用容器自带(若存在)的同名函数。

    map<int, string> mymap;
    mymap.insert(std::make_pair(1, "wang"));
    mymap.insert(std::make_pair(2, "li"));
    auto finditer = mymap.find(2);
    if(finditer != mymap.end()){
    	cout<<"find"<<endl;
    	cout<<iter->first<<iter->second<<endl;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. find_if
    vector<int> myvector = {10, 20, 30, 40, 50};
    auto finditer = find_if(myvector.begin(), myvector.end(), [](int val){ //可调用对象
    	if(val>15)
    		return true; //返回第一个满足规则的元素
    	return false;
    });
    if(finditer != myvector.end())
    	cout<<"find"<<*finditer<<endl;
    else
    	cout<<"not find"<<endl;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    1. sort
    vector<int> myvector = {10, 20, 30, 40, 50};
    //sort(myvector.begin(), myvector.end());//默认升序
    sort(myvector.begin(), myvector.begin()+3);//前三个元素升序
    
    • 1
    • 2
    • 3
    bool myfuncsort(int i, int j){
    	//return i
    	return i>j;//降序
    }
    sort(myvector.begin(), myvector.end(), myfuncsort);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    class A{
    public:
    	bool operator()(int i, int j){
    		//return i
    		return i>j;//降序
    	}
    };
    
    A a;
    sort(myvector.begin(), myvector.end(), a);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    list<int> mylist = {10, 20, 30, 40, 50};
    //sort(mylist .begin(), mylist .end());//sort算法不适用于双向迭代器,只适用于随机访问迭代器
    mylist.sort(myfuncsort);//list容器自带sort成员函数
    
    • 1
    • 2
    • 3

    顺序容器可以排序,关联容器(含无序容器)不适合排序。

    map<int, string> mymap;
    mymap.insert(make_pair(50, "wang"));
    mymap.insert(make_pair(15, "li"));
    mymap.insert(pair<int, string>(80, "zhao"));
    //sort(mymap.begin(), mymap.end());//error
    
    • 1
    • 2
    • 3
    • 4
    • 5
    unordered_set<int> myset = {10, 20, 30, 40, 50};
    //sort(myset .begin(), myset .end());//error
    
    • 1
    • 2

    19.7 函数对象回顾、系统函数对象与范例

    19.7.1 函数对象/仿函数回顾

    函数对象(function objects)或仿函数(functors),配合算法使用实现特定功能,调用方式很统一,即:名字(参数列表)。
    函数对象形式整理

    • 函数:void func(int x) {…}
    • 可调用对象(类/类模板生成对象):class A{public:void operator()(int x){}};
    • lambda表达式:[](int x){};

    19.7.2 标准库中定义的函数对象

    #include 
    
    • 1
    1. 算术运算类
    表达式(函数对象)效果
    negate<类型>()-param
    plus<类型>()param1+param2
    minus<类型>()param1-param2
    multiplies<类型>()param1*param2
    divides<类型>()param1/param2
    modulus<类型>()param1%param2
    1. 关系运算类
    表达式(函数对象)效果
    equal_to<类型>()param1==param2
    not_equal_to<类型>()param1!=param2
    less<类型>()param1
    greater<类型>()param1>param2
    less_equal<类型>()param1<=param2
    greater_equal<类型>()param1>=param2
    1. 逻辑运算符
    表达式(函数对象)效果
    logical_not<类型>()!param
    logical_and<类型>()param1&¶m2
    logical_or<类型>()param1||param2
    1. 位运算类
    表达式(函数对象)效果
    bit_xor<类型>()param1^param2
    bit_and<类型>()param1¶m2
    bit_or<类型>()param1|param2
    template<class _Ty = void>
    struct plus{
    	constexpr _Ty operator()(const _Ty& _Left, const _Ty& _Right) const {
    		return _Left + _Right;
    	}
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    cout<<plus<int>()(4, 5)<<endl;
    //plus实例化类
    //plus()临时可调用对象(重载了operator())
    //plus()(4, 5)函数调用
    
    • 1
    • 2
    • 3
    • 4

    19.7.3 标准库中定义的函数对象范例

    vector<int> myvector = {10, 20, 30, 40, 50};
    sort(myvector.begin(), myvector.end(), greater<int>());
    sort(myvector.begin(), myvector.end(), less<int>());
    //greater()和less()产生临时的可调用对象
    
    • 1
    • 2
    • 3
    • 4

    19.8 适配器概念、分类、范例与总结

    19.8.1 适配器基本概念

    类似于转接头。将一个既有东西进行适当改造,增减一点东西,就会成为一个适配器。

    19.8.2 容器适配器

    stack和queue归类为容器适配器,将既有的deque进行适当的改造(阉割一点东西)。

    template<class _Ty, class _Container = deque<_Ty>>
    class queue {
    public:
    	//...
    	void push(value_type && _Val){
    		c.push_back(_STD move(_Val));
    	}
    protected:
    	_Container c;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    19.8.3 算法适配器

    算法是函数模板,算法适配器就是函数适配器,最典型的是绑定器(Binder)。
    bind,函数模板,算法适配器中的绑定器。

    vector<int> myvector = {50, 15, 80, 30, 46, 80};
    int cishu = count(myvector.begin(), myvector.end(), 80);
    cout << cishu <<endl;
    
    • 1
    • 2
    • 3
    class A{
    public:
    	bool operator()(int i){
    		return i>40;
    	}
    };
    
    A a;
    cishu = count_if(myvector.begin(), myvector.end(), a);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    template<class _Ty = void>
    struct less{
    	constexpr bool operator()(const _Ty& _Left, const _Ty& _Right) const {
    		return _Left < _Right;
    	}
    };
    
    class A{
    public:
    	bool operator()(int i){
    		//return i>40;
    		return 40<i;
    	}
    };
    
    //less()中operator()第一个参数绑定了40
    auto bf = bind(less<int>(), 40, placeholders::_1);
    bf(19);//调用,第二个参数19
    
    cishu = count_if(myvector.begin(), myvector.end(), bind(less<int>(), 40, placeholders::_1));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    19.8.4 迭代器适配器

    方向迭代器就是一个迭代器适配器。

    vector<int> iv = {100, 200, 300};
    for(vector<int>::reverse_iterator riter = iv.rbegin(); riter != iv.rend(); riter++)
    	cout<<*riter<<endl;
    
    • 1
    • 2
    • 3

    19.8.5 总结

  • 相关阅读:
    4.Python建造者模式
    ASEMI光伏二极管GMK4045,GMK4045特征,GMK4045应用
    更多龙蜥自研特性!生产可用的 Anolis OS 8.6 正式发布
    WebGL:基础练习 / 简单学习 / demo / canvas3D
    VS2019 error LNK2001: 无法解析的外部符号 解决方法
    【资损】系统迭代过程中的兼容性设计
    C++中类模板的语法与使用
    vue3 动态组件
    Java基于SSM开发的企业员工管理系统源码
    ThreadLocal
  • 原文地址:https://blog.csdn.net/oqqyx1234567/article/details/127317176