zoukankan      html  css  js  c++  java
  • C++ STL vector容器学习

      STL(Standard Template Library)标准模板库是C++最重要的组成部分,它提供了一组表示容器、迭代器、函数对象和算法的模板。其中容器是存储类型相同的数据的结构(如vector,list, deque, set, map等),算法完成特定任务,迭代器用来遍历容器对象,扮演容器和算法之间的胶合剂。   

    模板类vector
      在计算中,矢量(vector)对应数组,它的数据安排以及操作方式,与array非常类似。在C++中,使用vector模板类时,需要头文件包含#include<vector>,并声明使用using std::vector或者using namespace std;
    (1)vector初始化
    要创建vector模板对象,可使用<type>表示法来指出所使用的类型,vector通过类函数重载,支持多种初始化方式。
     int a[5] = {5, 1, 2, 0, 3};
     vector<int> v0(a, a+5);    
     vector<int> v1(v0);
     vector<int> v2(v0.begin(), v0.begin()+2);
     vector<int> v3(5);
    如果编译器支持C++11, 可以采用列表初始化,结果相同。
     vector<int> v{5, 1, 2, 0, 3};

    (2)vector方法

    C++ STL除了分配空间外,还提供了一些基本方法,下面将详细讲解这些方法。
    assign 分配指定区间的数据给容器
    v2.assign(v1.end()-v1.size()/2, v1.end());
    v2.assign(a, a+2);
    
    push_back 向容器的末尾添加元素,容器内元素个数加1
    pop_back 删除容器尾端元素,容器内元素个数减1.
    v1.push_back(rand()%100); 
    v1.pop_back();
    size 容器内当前元素个数
    capacity 容器当前容量
    empty 判断容器是否为空
    cout<<v1.size()<<endl;     
    cout<<v1.capacity()<<endl; 
    if(!v1.empty())
    {
        v1.pop_back();
        cout<<"v1 is not empty!"<<endl;     
    }   
    resize 修改当前容器内元素个数,大于当前数则插入相应数据,小于则删除末尾相应区间。
    reserve 修改当前容器容量,大于当前容量则申请相应空间,小于则不处理。
    v1.resize(9, 6);           
    v1.reserve(14);            
    insert 在容器指定区间插入一个或者多个元素
    earse 删除容器内一个或者指定区间内所有元素
    v0.insert(v0.begin(), a[0]);          
    v1.insert(v1.begin(), a, a+2);       
    v1.insert(v1.begin(), v0.begin()+2, v0.begin()+4); 
        
    v1.earse(v1.end()-6);                 
    v1.earse(v1.end()-6, v1.end());  
    front 返回容器的第一个元素
    back  返回容器的最后一个元素
    cout<<v1.front()<<endl; 
    cout<<v1.back()<<endl;
    clear 清空容器内元素,仅修改size,不影响容器容量
    swap  交换两容器内内容,用于容量收缩
     v1.clear();
     vector<int>().swap(v1);
    begin 返回指向vector首位的迭代器
    end   返回指向vector末位的迭代器
    基于迭代器,就可以简单的实现vector的遍历。
    for(vector<int>::iterator iter0=vt1.begin(); iter0!=vt1.end(); iter0++)
    {cout<<*iter0;}

    当然,C++11提供了类型推导,上述语句可简化为为

    for(auto iter0=vt1.begin(); iter0!=vt1.end(); iter0++)
    {cout<<*iter0;}
    不过vector重载了[]运算符,也可以用
    for(unsinged int i=0; i<vt1.size(); i++)
    {cout<<vt1[i];}
    在下小节中,将根据STL提供算法,用于更方便的遍历和处理vector。
    (3)用于vector的算法(常见算法)
      STL提供大量的算法用于容器的操作,这里主要以常用的for_each(遍历), sort(排序), random_shuffle(随机排列)三种算法来简单演示STL算法的应用,使用算法要包含头文件#include <algorithm>。
      for_each 遍历容器,将被指向的函数应用于容器区间的每个元素。
    void ShowInt(int &s)
    {
       cout<<s<<" ";
    }
    for_each(v1.begin(), v1.end(), ShowInt);
     //C++11支持lambada表达式,可以写成一句话:
    for_each(v1.begin(), v1.end(), [](int &s){
            cout<<s<<" ";
    });

      sort 容器内对象元素按照指定的规则进行排序,默认按照从小到大排列(不包含比较函数),当然也可以自定义比较函数

    bool CompareInt(int &t1, int &t2)
    {
        if(t1<t2)
          return true;
        return false;
    }
    sort(v1.begin(), v1.end(), CompareInt); 
    sort(v1.begin(), v1.end());
    //C++11 lambada
    sort(v1.begin(), v1.end(), [](int &t1, int &t2)->bool{
            if(t1<t2)
                 return true;
            return false;
    });
      lower_bound 返回不小于元素值的第一个迭代器(相等或者大于),值可被插入的第一个位置
      upper_bound 返回不破坏排序的情况下,值可被插入的最后一个位置
    auto iter0 = lower_bound(v1.begin(), v1.end(), 34);
    cout<<*iter0<<endl;          
    iter0 = upper_bound(v1.begin(), v1.end(), 34);
    cout<<*iter0<<endl;  

      random_shuffle 随机排列容器内元素,其中第三个变量为提供的自定义随机函数。

    random_shuffle(v1.begin(), v1.end());
    //C++11 lambada
    random_shuffle(v1.begin, v1.end(), [](const unsigned int n)->unsigned int{
            return rand()%n;
    });
    (4) vector用于自定义数据类型
      vector容器方便了对于数据的排序,插入,删除及遍历操作处理。结合运算符重载,类模板相关定义,将用户自定义数据类型通过vector进行管理,属于比较难以理解,但也是运用较多的部分。
      因为C++11取消了关键字export,也不建议使用,因此类模板的声明和实现,包括友元函数的实现都要声明在同一个文件内。
    /*****************************************
    #device.h
    #用户自定义类模板
    #命名空间 user
    #用户自定义类模板 device<T>
    #构造函数重载
    #一元、 二元运算符重载 
    *******************************************/
    #include <string>
    #include <iostream>
     
    using namespace std;
    namespace user
    {
        //自定义类模板
        template<class T>
        class device
        {
            public:
                //构造函数重载
                device(){}
                device(T a){id = a; name=" ";}
                device(string str){name = str; id=0;}
                device(string str, T a){name = str; id = a;}
                ~device(){};
                void show_info();
     
                //一元运算符重载
                device<T>& operator++(int);
     
                //二元运算符重载
                friend device<T>& operator+ <T>(device<T>&d, string &s);
                friend  bool operator< <T>(device<T> &d1, device<T> &d2);
                friend ostream& operator<< <T>(ostream &out, const device<T> &d);
            private:
                T        id;
                string    name;
        };
     
        template<class T>
        void device<T>::show_info(void)
        {
            cout<<"id:"<<id<<" ";
            cout<<"name:"<<name<<endl;
        }
     
        template<class T>
        ostream& operator<<(ostream &out, const device<T> &d)
        {
            out<<"id:"<<d.id<<" name:"<<d.name<<"
    ";
            return out;
        }
     
        template<class T>
        bool operator<(device<T> &d1, device<T> &d2)
        {
            if(d1.id < d2.id)
                return true;
            else if(d1.id == d2.id && d1.name<d2.name)
                return true;
            else
                return false;
        }
     
        template<class T>
        device<T>& device<T>::operator++(int)
        {
            this->id++;
            return *this;
        }
     
        template<class T>
        device<T>& operator+(device<T> &d, string &s)
        {
            d.name  = s + d.name;
            return d;
        }
    } 

     vectorDemo.cpp主要涉及智能指针,用户自定义类型及STL vector容器及算法的相应应用。

    /*****************************************
    #VectorDemo.cpp
    #vector容器方法
    #迭代器
    #STL算法
    #lambada表达式
    #智能指针
    *******************************************/
    #include "VectorDemo.h"
    #include <vector>
    #include <iostream>
    #include <algorithm>
    #include <memory>
    #include "device.h"
    #include <string>
     
    using namespace std;
    using namespace user;
    
    //函数模板
    template<class T>
    void ShowDevice(shared_ptr<device<T>> &s)
    {
        cout<<*s;
    }
     
    template<class T>
    void show_genericity_demo(vector<shared_ptr<device<T>>> &d)
    {
        //<<** 三次重载,第一次取智能指针,第二次取对象, 第三次输出
        for(auto iter=d.begin(); iter!=d.end(); iter++)
        {
            cout<<**iter; //(*iter)->show_info();
        }
        cout<<endl;
    }
     
    template<class T>
    bool genericity_compare(shared_ptr<device<T>> &d1, shared_ptr<device<T>> &d2)
    {
        //重载运算符< 比较
        if((*d1) < (*d2))
            return true;
        else
            return false;
    }
     
    //复杂容器vector模板,涉及智能指针和用户自定义类型
    int genericity_vector_Demo(void)
    {
        shared_ptr<device<int>> spd[5] = {
            shared_ptr<device<int>>(new device<int>("TV", rand()%100)),
            shared_ptr<device<int>>(new device<int>("Phone", rand()%100)),
            shared_ptr<device<int>>(new device<int>("Computer", rand()%100)),
            shared_ptr<device<int>>(new device<int>("light", rand()%100)),
            shared_ptr<device<int>>(new device<int>("pot", rand()%100)),
        };
        
        //vector容器创建和初始化,对象为device对应的智能指针
        vector<shared_ptr<device<int>>> vspd(spd, spd+5);
        
        //遍历显示vector中的所有对象,传入为shared_ptr指针,因此*号,在通过<< 运算符重载
        for_each(vspd.begin(), vspd.end(), ShowDevice<int>);
        cout<<endl;
     
        //排序 lambada表达式
         sort(vspd.begin(), vspd.end(), [](shared_ptr<device<int>> &t1, shared_ptr<device<int>> &t2)->bool{
                if((*t1)<(*t2))
                    return true;
                return false;
            });
     
        //乱序排列容器内对象
        random_shuffle(vspd.begin(), vspd.end());
        show_genericity_demo<int>(vspd);
     
        cout<<*vspd.front()<<endl;
        cout<<*vspd.back()<<endl;
     
        vspd.push_back(shared_ptr<device<int>>(new device<int>("icebox", rand()%100)));
        vspd.push_back(shared_ptr<device<int>>(new device<int>("PlayStation", rand()%100)));
        
        //排序,因为容器元素为智能指针,不支持省略比较函数方法
        sort(vspd.begin(), vspd.end(), genericity_compare<int>);
        show_genericity_demo<int>(vspd);
     
        vspd.pop_back();
        show_genericity_demo<int>(vspd);
     
        //遍历 +, ++运算符重载,实现对容器内对象元素修改.
        for_each(vspd.begin(), vspd.end(), [](shared_ptr<device<int>> &s){
            (*s) = (*s) + string("famlily ");
            (*s)++;
        });
        show_genericity_demo<int>(vspd);
     
        return 0;
    }  

      相关代码:容器范例下载

      参考书籍:

      1. C++ Primer Plus

           2. STL源码剖析

  • 相关阅读:
    Exp4 恶意代码分析 Week6
    Exp3 免杀原理与实践 Week5
    Exp2 后门原理与实践 Week4
    Exp1 PC平台逆向破解 Week3
    Exp0 Kali安装 Week1
    2018-2019-2 《网络对抗技术》Exp9 WebGoat 20165326
    2018-2019-2 《网络对抗技术》Exp8 Web基础 20165326
    2018-2019-2 《网络对抗技术》Exp7 网络欺诈防范 20165326
    2018-2019-2 《网络对抗技术》Exp6 信息搜集与漏洞扫描 20165326
    2018-2019-2 《网络对抗技术》Exp5 MSF基础应用 20165326
  • 原文地址:https://www.cnblogs.com/zc110747/p/5466088.html
Copyright © 2011-2022 走看看