• 跟我一起学STL(2)——vector容器详解


    一、引言

    在上一个专题中,我们介绍了STL中的六大组件,其中容器组件是大多数人经常使用的,因为STL容器是把运用最广的数据结构实现出来,所以我们写应用程序时运用的比较多。然而容器又可以序列式容器和关联式容器两类,C++语言本身提供了一个序列式容器数组,另外STL又提供vector,list,deque等序列式容器,本专题将详细介绍下vector容器。

    二、vector详解

    2.1 vector容器介绍

    vector容器的数据结构为单端数组,其操作方式与数组的操作非常相似,唯一不同的是——数组是静态空间,一旦配置了数组大小就不能改变,而vector是动态空间,随着元素的插入,vector类内部机制会自行扩充空间来容纳新的元素,我们不需要担心因为空间不足而一开始就申请一个空间较大的数组,使用vector更加灵活。vector与C++中数组的区别,如.NET中List<T>类与数组的区别一样。

    2.2 vector对象创建详解

    vector有8个构造函数,其8个构造函数的定义如下代码所示:

           // 默认无参构造函数
     vector()
            : _Mybase()
            {    // construct empty vector
            }
            // 
        explicit vector(const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct empty vector with allocator
            }
    
        explicit vector(size_type _Count)
            : _Mybase()
            {    // construct from _Count * _Ty()
            resize(_Count);
            }
    
       vector(size_type _Count, const _Ty& _Val)
            : _Mybase()
            {    // construct from _Count * _Val
            _Construct_n(_Count, _STD addressof(_Val));
            }
    
        vector(size_type _Count, const _Ty& _Val, const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct from _Count * _Val, with allocator
            _Construct_n(_Count, _STD addressof(_Val));
            }
            // 拷贝构造函数
        vector(const _Myt& _Right)
            : _Mybase(_Right._Alval)
            {    // construct by copying _Right
            if (_Buy(_Right.size()))
                _TRY_BEGIN
                this->_Mylast = _Ucopy(_Right.begin(), _Right.end(),
                    this->_Myfirst);
                _CATCH_ALL
                _Tidy();
                _RERAISE;
                _CATCH_END
            }
           
        template<class _Iter>
            vector(_Iter _First, _Iter _Last)
            : _Mybase()
            {    // construct from [_First, _Last)
            _Construct(_First, _Last, _Iter_cat(_First));
            }
    
        template<class _Iter>
            vector(_Iter _First, _Iter _Last, const _Alloc& _Al)
            : _Mybase(_Al)
            {    // construct from [_First, _Last), with allocator
            _Construct(_First, _Last, _Iter_cat(_First));
            } 

    下面演示下利用上面的构造函数来创建不同的vector对象,并输出每个vector对象中的元素,具体演示代码如下所示:

    // 额外引入vector头文件
    #include <vector>
    #include <iostream>
    using namespace std;
    void main()
    {
        // 使用_Vector_iterator<int>类默认无参构造函数初始化6个迭代器对象
        vector<int>::iterator v1_Iter,v2_Iter,v3_Iter,v4_Iter,v5_Iter,v6_Iter;
        // 创建一个空的vector对象v0,调用了①构造函数
        vector<int> v0;
    
        // 创建vector对象v1,v1包含3个默认值为0的元素,调用③构造函数
        vector<int> v1(3);
        // 创建vector对象v2,v2包含5个值为2的元素,调用④构造函数
        vector<int> v2(5,2);
        // 创建vector对象v3,v3包含3个值为1的元素和空间配置器,调用了⑤构造函数
        vector<int> v3(3,1,v2.get_allocator());
        // 创建了vector对象v2的拷贝v4,调用了⑥构造函数
        vector<int> v4(v2);
    
        // 创建一个临时vector对象并对对象元素进行初始化
        vector<int> v5(5);
        for(int index=0;index<5;index++)
        {
            v5[index]=index;
        }
        // 创建vector对象v6,调用⑦构造函数
        vector<int> v6(v5.begin()+1,v5.begin()+2);
        // 输出v1容器元素
        cout<<"v1=";
        for(v1_Iter=v1.begin();v1_Iter!=v1.end();v1_Iter++)
        {
            cout<<" "<<*v1_Iter;
        }
        cout<<endl;
    
        // 输出v2容器元素
        cout<<"v2=";
        for(v2_Iter=v2.begin();v2_Iter!=v2.end();v2_Iter++)
        {
            cout<<" "<<*v2_Iter;
        }
        cout<<endl;
    
        // 输出v3容器元素
        cout<<"v3=";
        for(v3_Iter=v3.begin();v3_Iter!=v3.end();v3_Iter++)
        {
            cout<<" "<<*v3_Iter;
        }
        cout<<endl;
    
        // 输出v1容器元素
        cout<<"v4=";
        for(v4_Iter=v4.begin();v4_Iter!=v4.end();v4_Iter++)
        {
            cout<<" "<<*v4_Iter;
        }
        cout<<endl;
        cout << "v5 =";
        for ( v5_Iter = v5.begin( ) ; v5_Iter != v5.end( ) ; v5_Iter++ )
        {
            cout << " " << *v5_Iter;
        }
        cout << endl;
    
        cout << "v6 =";
        for ( v6_Iter = v6.begin( ) ; v6_Iter != v6.end( ) ; v6_Iter++ )
        {
            cout << " " << *v6_Iter;
        }
        cout << endl;
        // move(v2)返回v2类型即vector类型,v7是通过拷贝构造函数进行创建的
        vector<int> v7(move(v2));
        vector <int>::iterator v7_Iter;
        cout << "v7 =";
        for ( v7_Iter = v7.begin( ) ; v7_Iter != v7.end( ) ; v7_Iter++ )
        {
            cout << " " << *v7_Iter;
        }
        cout << endl;
    }

    上面演示代码运行结果如下图所示:

    2.3 vector元素操作

    vector类中提供了很多成员函数,下面演示下一些常用函数使用,具体演示代码如下:

    #include <vector>
    #include <iostream>
    using namespace std;
    
    void print(vector<int> &v)
    {
        for(size_t i=0;i<v.size();i++)
        {
            cout<<v[i]<<" ";
        }
        cout<<endl;
    }
    
    void main()
    {
        #pragma region 元素的遍历访问
        // 可以采用数组下标、at()函数和迭代器的方式进行遍历访问
        vector<int> vint;
        // 向尾端插入一个元素20
        vint.push_back(20);
        vint.push_back(11);
        vint.push_back(12);
        vint.push_back(25);
        // 使用数组小标方式
        cout<<"vint[1] = "<<vint[1]<<endl;
        for(size_t i=0;i <vint.size();i++)
        {
            // 数组小标访问
            //cout<<"vint["<<i<<"] = "<<vint[i]<<" ";
        
            // 使用at函数访问
            cout<<"vint["<<i<<"] = "<<vint.at(i)<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 利用erase函数删除元素
        // 删除第二个元素,即删除11
        vint.erase(vint.begin()+1);
        cout<<"删除第一个元素后:"<<endl;
        int index1;
        vector<int>::iterator iter; 
        // 使用迭代器访问元素
        for(iter=vint.begin(),index1=0;iter!=vint.end();iter++,index1++)
        {
            cout<<"vint["<<index1<<"] = "<<*iter<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 利用pop_back函数删除尾部元素
        // 调用pop_back删除尾部元素,即删除25
        vint.pop_back();
        cout<<"删除最后一个元素后:"<<endl;
        vector<int>::iterator iter1;
        int j;
        // 使用迭代器访问元素
        for(iter1=vint.begin(),j=0;iter1!=vint.end();iter1++,j++)
        {
            cout<<"vint["<<j<<"] = "<<*iter1<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 反向遍历 vector 的元素
        // 调用inser把元素插入到vector容器中指定位置
        // 插入11到容器中第二个位置
        vint.insert(vint.begin()+1,11);
        // 插入25到容器中最后一个位置,等效于push_back函数
        vint.insert(vint.end(),25);
        vector<int>::iterator iter2;
        int k;
        cout<<"insert两个元素后容器元素为:"<<endl;
        // 使用迭代器访问元素
        for(iter2=vint.begin(),k=0;iter2!=vint.end();iter2++,k++)
        {
            cout<<"vint["<<k<<"] = "<<*iter2<<" ";
        }
        cout<<endl;
        cout<<"反向遍历的结果为:"<<endl;
        vector<int>::reverse_iterator riter;
        int index;
        for( riter=vint.rbegin(),index=0;riter!=vint.rend();riter++,index++)
        {
            cout<<"vint["<<index<<"] = "<<*riter<<" ";
        }
        cout<<endl;
        #pragma endregion 
    
        #pragma region 两个vector容器元素的交换
        // 创建vector<int>对象vint2
        vector<int> vint2;
        vint2.push_back(1);
        vint2.push_back(2);
        vint2.push_back(3);
        // 把vint与vint2进行交换
        //swap(vint,vint2);
        vint.swap(vint2);
        cout<<"vint与vint2交换后的结果:"<<endl;
        cout<<"vint = ";
        print(vint);
        cout<<"vint2 = ";
        print(vint2);
        #pragma endregion 
        
    }

    上面代码的运行结果为:

    三、小结

    到这里,本专题的内容介绍结束了,vector向量容器实现为数据线性存储的泛型类,本文介绍了使用数组下标、at()函数和迭代器方式来进行元素访问,然后演示了一些常用函数的使用。vector尾部添加和移除元素效率非常高,但在中部或头部插入元素和删除元素效率较低,这与它的数据结构(线性连续存储方式)有着密切的关系。

  • 相关阅读:
    vue代码调试
    在vscode中无法使用yarn
    js滚动条计算公式
    chrome插件制作-高级篇
    网站js注入实现自动输入账号密码
    String、StringBuffer和StringBuilder有什么区别?
    待重写
    http协议
    待重写
    java内存加载机制
  • 原文地址:https://www.cnblogs.com/zhili/p/STLvector.html
Copyright © 2020-2023  润新知