• stl——vector详解


    stl——vector详解

    stl——vector是应用最广泛的一种容器,类似于array,都将数据存储于连续空间中,支持随机访问。相对于array,vector对空间应用十分方便、高效,迭代器使vector更加灵活、安全。设计皆由vector起,键盘之下尽vector。

    1 vector本质

        vector数据结构如下,通过三个迭代器start, finish, end_of_storage的系列public接口,可很好地完成数据存储、溢出判断(iter >= iv.end())、大小、容量(容量与大小不等,以免不断申请空间耗费资源)、重载操作符[]、判空、最前元素、最后元素等等。

    class vector{
    
    protected:
    
        iterator  start ; 
    
        iterator  finish; 
    
        iterator  end_of_storage;
    
    public:
    
        iterator  begin () { return  start ; } 
    
        iterator  end() { return  finish; } 
    
        size_type size() const { return size_type( end() - begin()); } 
    
        size_type capacity() const { return size_type(end_of_storage - begin()); } 
    
        bool empty () const { return begin() == end(); } 
    
        reference operator[] (size_type n) { return *(begin() + n); } 
    
        reference front () { return  *begin(); } 
    
    }

        由于vector是用连续空间存储数据,不断扩容将导致大量的新空间申请、元素拷贝和释放原有空间,十分耗时,vector申请空间时,都将多申请部分空间备用,如下图的[finish, end_of_storage)所示。只有当finish == end_of_storage时,再申请新的空间(2*capacity()), 图2就是在图1的基础上,再插入元素引起的空间变化时的数据存储情景。

    image

    图1 vector数据存储-1

        在图1和图2中的start不再指向相同的地址,扩大空间是新请新的更大的空间,因而不仅是start迭代器,其它指向空间变化前vector的迭代器都将失效。此处极易引起bug。

    image图2 vector数据存储-2

    2 vector常用方法与技巧

    1、空间申请

        构造函数、reserve()、resize()。

      1: vector<int> iv(3, -1);
    
      2: iv.reserve(10);
    
      3: iv.resize(10, -1);

         构造函数不述;

         reserve(n),申请空间,等同于扩大[finish, end_of_storage),当n <= capacity()时,无效,可以理解为主要改变end_of_storage(或capacity)——reserve()匹配capacity();

         resize(10),申请空间并赋值,等同于改变[start, finish),可以理解为主要改变finish(或size())——resize()匹配size()。

    2、空间释放

        erase()、resize()、clear()均仅改变finish(或size()),不改变end_of_storage。

        swap()释放空间——清空,改变end_of_storage:

    vector<int> iv(10, -1);
    
    iv.reserve(500);
    
    vector<int>().swap(iv);//交换空间
    
    cout<<iv.capacity()<<endl;//输出0

        swap()释放空间——释放多余空间,改变end_of_storage:

    vector<int> iv(10, -1);
    
    iv.reserve(500);
    
    vector<int>(iv).swap(iv);//交换空间
    
    cout<<iv.capacity()<<endl;//输出10

    3、resize()与operator []

        operator []使得vector与array处理完全类似,但operator []极易引起异常与错误,如下:

    vector<int> iv();
    
    iv.reserve(500);
    
    iv[300] = -1;
    
    cout<<iv.capacity()<<endl;//输出500
    
    cout<<iv.size()<<endl;//输出0

         这里就引起了迭代器不符合预期,也不知道什么才是预期。建议用法为resize()与operator []一起使用,从而使得操作完全等同于array,且安全:

    vector<int> iv();
    
    iv.resize(500, 0);
    
    iv[300] = -1;
    
    cout<<iv.capacity()<<endl;//输出500
    
    cout<<iv.size()<<endl;//输出500

    4、vector迭代器

        vector的迭代器十分简单,等同于指针,++、--、+n、-n、>、<、!=等操作都可应用——random access iterator,基本上全部stl algorithms均可以在此上应用。

        PS:强烈不推荐使用>,<,≤,≥之类比较迭代器,遍历时直接使用!=即可,以免混于其它非random access iterator的容器。

    参考资料:

    1、侯捷. STL源码剖析;

    2、侯捷. STL源码剖析注释;

    对于同仁们的布道授业,一并感谢。

    ----

    只能永远把艰辛的劳动看作是生命的必要;即使没有收获的指望,也能心平气和的继续耕种。
     
    分类: stl详解
    标签: stlvector
  • 相关阅读:
    第一只猫环境准备
    高阶Promise--async
    操作系统源码编译心得
    闭包的应用场景
    全栈微信小程序商城 学习笔记10.1 对更新收货地址接口做权限控制
    全栈微信小程序商城 学习笔记9.1 新建登录接口
    全栈微信小程序商城 学习笔记8.5 product分类商品接口编写
    全栈微信小程序商城 学习笔记8.4 category分类接口编写
    全栈微信小程序商城 学习笔记8.3 product最近新品接口编写
    全栈微信小程序商城 学习笔记8.2 theme详情接口编写
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3256852.html
Copyright © 2020-2023  润新知