zoukankan      html  css  js  c++  java
  • 【C++基金会 04】vector详细解释

    根据写博客开始总有一些事情的习惯,加鸡汤文,今天请原谅我记得。

    =============================================


    今天要写的内容是顺序型容器。首先,标准库定义了三种顺序容器类型:vector,list和deque(双端队列),这篇博客介绍的是vector容器。

    首先要知道。vector不是一种数据类型,而是一个类模板,能够用来定义随意多种数据类型。比方说vector<int>是一种数据类型。vector<string>也是一种数据类型。使用vector之前我们要先包括头文件

    #include<vector>
    using std::vector;

    1.vector初始化

    vector<T> v1;       //初始化一个为空的vector
    vector<T> v2(v1);   //v2是v1的一个副本
    vector<T> v3(n,i);  //n个值为i的vector
    vector<T> v4(n);    //v4含n个默认初始化值的vector(如int默认0。string默认"")

    2.迭代器

    每一个标准库容器类型都定义了名为iterator的成员。也就是迭代器。迭代器所指向的类型为vector容器中实际存储的类型,比方

    vector<int>iterator iter;
    迭代器经常使用于遍历容器。最常见的便是begin和end操作,vector.begin()返回vector中的第一个元素,vector.end()返回末端元素的下一个。

    vector<int> ivec;
    for(int i = 0; i <= 10; i++)
      ivec.push_back(i);
    
    for(vector<int>::iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
    {
      *iter = 0;   //遍历vector,更改值为0
    }
    须要注意的是,假设有元素加入或者删除,会使迭代器失效,从而须要调整迭代器的值。否则非常可能会导致执行时崩溃。者点非常重要。

    3.vector的经常使用操作

    加入:须要注意的是加入新元素可能会使迭代器失效,所以程序须要保证迭代器在插入或者push操作后能得到更新。

    //加入元素
    v.push_back(t);               //在vector尾部加入一个元素t
    v.insert(iter,t);            //在迭代器iter所指向的元素前面插入元素t,返回新加入的元素的迭代器
    v.insert(iter,n,t);          //在迭代器iter所指向的元素前面插入n个元素t,返回void
    v.insert(iter,iter1,iter2);  //在迭代器iter所指向的元素前面插入迭代器[iter1,iter2)之间的元素(左闭右开)。返回void

    全部容器类型都支持关系操作符来比較大小,规则是:

    //v1和v2长度和全部元素都相等。则v1=v2,否则不等。

    //v1长度小于v2,可是v1全部元素和v2 相等,则 v1 < v2。 //v1和v2元素不等,则比較结果取决于第一个不相等的元素。

    vector大小的操作:

    v.size();      //返回v中元素的个数,返回类型 v::size_type
    v.max_size();  //返回v可容纳最多元素个数
    v.empty();     //推断是否为空
    v.resize(n);   //调整v长度大小,使其能容纳n个元素。假设n<v.size(),则删除多出来的元素,否则加入採用值初始化的元素
    v.resize(n,t); //调整v长度大小,使其能容纳n个元素,全部新加入的元素值都为t

    vector訪问:

    v.back();   //返回v最后一个元素的引用
    v.front();  //返回v第一个元素的引用
    v[n];       //返回v下标为n的引用
    v.at[n];    //返回v下标为n的引用
    
    //返回的是引用,注意和迭代器的差别,迭代器返回的是指针
    vector<int> v;
    //迭代器
    vector<int>::iterator iter = v.begin();
    //引用,以下val = val2
    vector<int>::reference val = v.front();
    vector<int>::reference val2 = *v.begin();
    vector删除操作:

    v.erase(iter);        //删除iter所指向的元素,返回iter下一个元素
    v.erase(iter1,iter2); //删除[iter1,iter2)之间的元素(左闭右开)
    v.clear();            //全删,返回void
    v.pop_back();         //删除最后一个。返回void

    赋值操作:

    v1 = v2;                //复制v2到v1
    v1.swap(v2);            //交换内容:交换v1和v2之间的元素,速度比v2拷贝到v1快
    v1.assign(iter1,iter2); //又一次设置:将[iter1,iter2)之间的元素(左闭右开)拷贝到v中
    v1.assign(n,t);         //又一次设置:将v中又一次设置为n个值为t的元素
    注意swap不会使迭代器失效。

    assign会将vector中全部元素删除,然后再插入新元素。assing能够用于:同样或者不同的容器内,元素类型不同可是相互兼容之间的转换赋值。(比方vector<char*>和list<string>之间的赋值)

    vector<char*> v1;
    for(int i = 0; i <= 10; i++)
      v1.push_back("dddd");
    list<string> list1;
    list1.assign(v1.begin(),b1.end());

    4.vector容器自增长

    首先要明确vector容器的元素在内存中是以连续的方式存放。

    想一下假设加入新元素的时候时候已经没有空间来容纳新元素,又不能随便找个地儿来放新元素。所以须要又一次分配vector的存储空间:copy旧元素到新存储空间。插入新元素。删除旧存储空间。

    假设vector在每次加入新元素的时候都这么搞一个那效率何在?所以。显然vector设计的时候也考虑到这方面的问题,作者使用的内存分配策略是:以最小的代价连续存储元素。

    用通俗大大白话来讲,就是每次分配的时候会比你当前所须要的空间多一些,当已经分配的空间使用完后才会开辟新的空间。

    首先来看一下capacity和reserve操作

    v.size();     //返回vector中元素的个数
    v.capacity(); //返回vector可以存储的元素总数
    v.reserve(n); //手动设置vector容器应该预留n个元素的空间
    举一个简单的样例来说明他们之间的关系:

    vector<int> v;
    cout<<"vector size:"<<v.size()<<endl;        //输出0
    cout<<"vector capacity:"<<v.capacity()<<endl;//输出0
    
    //加入24个元素
    for(int i = 0; i < 24; i++)
      v.push_back(i);
    
    cout<<"vector size:"<<v.size()<<endl;        //输出24
    cout<<"vector capacity:"<<v.capacity()<<endl;//输出32
    明确了吧。capacity总是要大于或等于size的。至于为什么是32?由于每当vector不得不分配新的存储空间时,会以加倍当前容量 的分配策略来又一次分配。比方你加入1个元素。size为1,capacity也为1,然后再加入,capacity 乘2,然后再加入再乘2。例如以下:

    //加入的时候size和capacity的关系:
    //v.size() —— v.capacity()
            0  -  0
            1  -  1
            2  -  2
            3  -  4
            4  -  4
            5  -  8
            9  -  16
            以此类推...
    或者我们能够自己设置预留空间,改动上面的样例:

    vector<int> v;
    v.reserve(50);
    cout<<"vector size:"<<v.size()<<endl;        //输出0
    cout<<"vector capacity:"<<v.capacity()<<endl;//输出50
    //加入50个元素
    for(int i = 0; i < 50; i++)
      v.push_back(i);
    //再多加入一个
    v.push_back(51);
    cout<<"vector size:"<<v.size()<<endl;        //输出51
    cout<<"vector capacity:"<<v.capacity()<<endl;//输出100

    5.容器优缺点:

    vector:长处:高速随机訪问

    缺点:在容器任何位置插入或删除,比在容器尾部插入或删除,开销大。

    list:是不连续存储的,长处:在容器中不论什么位置高效的插入和删除元素。

    缺点:不支持随机訪问。訪问元素须要遍历其它元素。

    deuqe :拥有更复杂的数据结构。长处:从容器两端插入和删除都非常快,支持高效随机訪问。缺点:在中间插入或删除效率非常低。

    6.推断选择哪种容器:

    (1)须要高效随机訪问元素,则使用vector或者deque。

    (2)须要高效在容器中间位置插入或者删除元素,则使用list。

    (3)若不是在中间位置插入,而是容器首部或者尾部插入,则使用deque。

    (4)若既须要高效随机訪问又须要高效中间插入,则能够将元素加入到list中然后排序啥的。再拷贝到vector中。


    =========================================


    再不睡觉就作死了。。


    转载请注明出处:http://blog.csdn.net/shun_fzll/article/details/37917133


    版权声明:本文博客原创文章,博客,未经同意,不得转载。

  • 相关阅读:
    我是如何用三小时搞出个赚钱产品的?
    搭建一个基于nuxt.js的项目
    栅格系统
    git使用
    通过JS获取屏幕高度,借助屏幕高度设置div的高度
    如何理解盒模型
    e.target.value 和 this 的区别
    组件化设计:弹窗的使用逻辑
    uni-app 入坑记
    MAC 系统快捷键
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4713639.html
Copyright © 2011-2022 走看看