• 【STL源码学习】细品vector


    第一节:vector简介
    vector是一种典型的类模板,使用的时候必须进行实例化。
    vector的数据存储在数组上,支持随机访问迭代器,支持下标操作[]和at操作,支持手动扩容和自动容量增长。
    vector是STL中的最常用容器,并支持STL的通用算法。
    第二节:vector的迭代器介绍
    vector支持iterator、const_iterator、reverse_iterator、const_reverse_iterator,前两个是正向迭代器,后两个是逆向迭代器。
    迭代器支持操作:*操作符、->操作符、前后++、前后--、+=、+、-、==、!=、[]、<、>、<=、>=
    第三节:需重新定向iterator的场景
    1.vector内存重分配
    vector支持容量自动增长,扩展容量(自动增长或手动操作增长容量)的时候会申请一块更大的内存并将现有数据拷贝过去,此时所有的迭代器都会失效,需重新指向。测试insert导致容量自动增长时,已有的迭代器全部失效。vector的容量自动增长方式经测试并不是翻倍增长模式。
    2.vector交换
    swap以后迭代器仍指向交换前的元素储存位置,等于失效,需重新指向。
    3.vector删除元素
    erase以后vector上的所有迭代器都失效,需重新指向。
    第四节:vector使用小贴士
    vector的下标操作[]和at仅用来对已经插入的元素进行取值和赋值,不能用来insert。
    vector默认容量较小,可以通过指定较大初始容量的方式避免vector多次自动增长带来的性能损耗,可以指定容量的操作有:构造和复制构造、reserve、resize、assign。
    vector<typename>可以用iterator和const_iterator迭代器,而const vector<typename>只能使用const_iterator。
    第五节:让vector更高效
    vector支持的泛型算法,即STL算法,鄙人比较菜,STL的算法还没懂,下次更新吧。
    第六节:vector常用方法
    构造函数:
    根据分配器构造、构造指定容量的vector、构造含有count个val的vector、
    复制构造函数:
    根据已有的vector构造,要求类型一致。
    重载操作符:
    操作符= 进行赋值
    push_back:尾插法插入元素,如果当前容量不足,就多申请一个空间。
    insert:
    有三个重载版本,插入单个元素至指定的迭代器后面、插入count个val到iter后、将两个迭代器之间的元素插入指定的iter后。
    reserve:
    扩展指定的容量。
    capacity:
    返回vector的总容量,还有一些标准库未要求,vs2010实际支持的扩展。
    begin、end、rbegin、rend、cbegin、cend、crbegin、crend
    resize:
    可以减少容量,也可以增加容量。有多种重载版本。
    size:
    已经容纳元素的数量。
    empty:
    已容纳元素数量是否为0.
    at  & []:
    操作类似string的操作,以0作为第一个元素的位置,返回装载的元素。
    data:
    返回指向第一个元素的指针。
    front:
    抛出第一个元素。
    back:
    抛出vector最后一个元素。
    pop_back:
    删除最后一个元素。
    assign:
    分配容量,具有数个重载版本:分配N个val元素的vector。
    erase:
    删除当前迭代器指向的元素,并返回指向下一个元素的迭代器、删除迭代器区间的元素并返回指向下一个元素的迭代器。
    clear:
    清理vector中的元素,并将size设置为0,不影响容量,据称对容纳元素的析构是在vector被析构时进行。
    swap:
    交换vector中的所有元素。
    第七节:vs2010自带vector头文件学习
    头文件编译的一些技巧,其他的实现就不骗点击量了。
    // vector standard header
    //避免重复编译的方式,和#ifndef/#define/#endif一样的作用
    #pragma once
    #ifndef _VECTOR_
    #define _VECTOR_
    #ifndef RC_INVOKED
    #include <xmemory>
    #include <stdexcept>
    //字节对齐方式,按照_CRT_PACKING指定的字节进行对齐,把原来的对齐方式压栈,并设置新的对齐方式为_CRT_PACKING
      #pragma pack(push,_CRT_PACKING)
    //指定告警级别为3
      #pragma warning(push,3)
    //编译器的一个技巧,#pragma push_macro("new") #undef new #pragma pop_macro("new"),这三个联合起来就是定义一个宏new并压入栈,取消new的定义,将压入栈的new弹出栈,这样做的目的是为了恢复new的本来含义,当包含的头文件中已经包含了宏new的定义时,这样做可以取消宏new的定义,而使用new的本来含义。在文件定义完毕后取消压入栈的宏new。
      #pragma push_macro("new")
      #undef new
    //让编译器忽视4127和4244号告警
    #pragma warning(disable: 4127)
    #pragma warning(disable: 4244)
    //将vector包含在命名空间std中,见宏定义可以很好理解:_STD_BEGIN和_STD_END两个宏完成namespace //std包含
    //#define _STD_BEGIN namespace std {  
    //#define _STD_END }    
    //#define _STD ::std::
    _STD_BEGIN
    #define _VECTOR_ORPHAN_RANGE (_ITERATOR_DEBUG_LEVEL == 2)
    // TEMPLATE CLASS _Vector_const_iterator
    template<class _Myvec>
    class _Vector_const_iterator
    : public _Iterator012<random_access_iterator_tag,
    //typename表示这是一个嵌套从属名称,而非类的静态成员变量
    typename _Myvec::value_type,
    typename _Myvec::difference_type,
    typename _Myvec::const_pointer,
    typename _Myvec::const_reference,
    _Iterator_base>
    { // iterator for nonmutable vector

    第八章:写在事后

    花了一天时间把vector的源码定义看了一遍,以为有所了解,等到写文章的时候和前辈一对比,才发现只是懂概念,根本谈不上巧妙应用,我有病曰浮夸,凡事了了而为,愿改之,坚持学习实践,我可是要成为海贼王的男人。

  • 相关阅读:
    两路归并算法
    个性化搜索引擎调研(三)
    编程珠玑开篇磁盘文件排序问题
    Lucene里经常被聊到的几个话题
    成就霸业的座右铭(绝对经典)
    别人对你的态度,决定了你的命运
    iBATIS缓存实现分析[转]
    Taste/Thoth:Taste Architecture 概览【转Beyond Search】
    中文分词算法笔记
    ConcurrentModificationException主要原因及处理方法
  • 原文地址:https://www.cnblogs.com/learn-my-life/p/3756719.html
Copyright © 2020-2023  润新知