C++ vector 容器浅析

本文深入介绍了C++标准库中的Vector容器,涵盖了其概念、特性、基本函数及应用场景,并提供了丰富的代码示例帮助理解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

原文地址:http://blog.youkuaiyun.com/w_linux/article/details/71600574

http://www.runoob.com/w3cnote/cpp-vector-container-analysis.html

http://blog.youkuaiyun.com/yamminy/article/details/69950114

http://blog.youkuaiyun.com/weierqiuba/article/details/65936076


一、什么是vector?

向量(Vector)是一个封装了动态大小数组的顺序容器(Sequence Container)。跟任意其它类型容器一样,它能够存放各种类型的对象。可以简单的认为,向量是一个能够存放任意类型的动态数组。


二、容器特性

1.顺序序列

顺序容器中的元素按照严格的线性顺序排序。可以通过元素在序列中的位置访问对应的元素。

2.动态数组

支持对序列中的任意元素进行快速直接访问,甚至可以通过指针算述进行该操作。操供了在序列末尾相对快速地添加/删除元素的操作。

3.能够感知内存分配器的(Allocator-aware)

容器使用一个内存分配器对象来动态地处理它的存储需求。


三、基本函数实现

1.构造函数
  • vector():创建一个空vector
  • vector(int nSize):创建一个vector,元素个数为nSize
  • vector(int nSize,const t& t):创建一个vector,元素个数为nSize,且值均为t
  • vector(const vector&):复制构造函数
  • vector(begin,end):复制[begin,end)区间内另一个数组的元素到vector中
   vector<int> a ;                                //声明一个int型向量a
        vector<int> a(10) ;                            //声明一个初始大小为10的向量
        vector<int> a(10, 1) ;                         //声明一个初始大小为10且初始值都为1的向量
        vector<int> b(a) ;                             //声明并用向量a初始化向量b
        vector<int> b(a.begin(), a.begin()+3) ;        //将a向量中从第0个到第2个(共3个)作为向量b的初始值
复制代码

除此之外, 还可以直接使用数组来初始化向量:
  int n[] = {1, 2, 3, 4, 5} ;
        vector<int> a(n, n+5) ;              //将数组n的前5个元素作为向量a的初值
        vector<int> a(&n[1], &n[4]) ;        //将n[1] - n[4]范围内的元素作为向量a的初值

其他
vector<int>obj={0,1,2,3,4,5,6,7,8,9}; //编译时加上 -std=c++11


2.增加函数

  • void push_back(const T& x):向量尾部增加一个元素X
  • iterator insert(iterator it,const T& x):向量中迭代器指向元素前增加一个元素x
  • iterator insert(iterator it,int n,const T& x):向量中迭代器指向元素前增加n个相同的元素x
  • iterator insert(iterator it,const_iterator first,const_iterator last):向量中迭代器指向元素前插入另一个相同类型向量的[first,last)间的数据

3.删除函数

  • iterator erase(iterator it):删除向量中迭代器指向元素
  • iterator erase(iterator first,iterator last):删除向量中[first,last)中元素
  • void pop_back():删除向量中最后一个元素
  • void clear():清空向量中所有元素

4.遍历函数

  • reference at(int pos):返回pos位置元素的引用
  • reference front():返回首元素的引用
  • reference back():返回尾元素的引用
  • iterator begin():返回向量头指针,指向第一个元素
  • iterator end():返回向量尾指针,指向向量最后一个元素的下一个位置
  • reverse_iterator rbegin():反向迭代器,指向最后一个元素
  • reverse_iterator rend():反向迭代器,指向第一个元素之前的位置

5.判断函数

  • bool empty() const:判断向量是否为空,若为空,则向量中无元素

6.大小函数

  • int size() const:返回向量中元素的个数
  • int capacity() const:返回当前向量张红所能容纳的最大元素值
  • int max_size() const:返回最大可允许的vector元素数量值

7.其他函数

  • void swap(vector&):交换两个同类型向量的数据
  • void assign(int n,const T& x):设置向量中第n个元素的值为x
  • void assign(const_iterator first,const_iterator last):向量中[first,last)中元素设置成当前向量元素

8.看着清楚

1.push_back 在数组的最后添加一个数据

2.pop_back 去掉数组的最后一个数据

3.at 得到编号位置的数据

4.begin 得到数组头的指针

5.end 得到数组的最后一个单元+1的指针

6.front 得到数组头的引用

7.back 得到数组的最后一个单元的引用

8.max_size 得到vector最大可以是多大

9.capacity 当前vector分配的大小

10.size 当前使用数据的大小

11.resize 改变当前使用数据的大小,如果它比当前使用的大,者填充默认值

12.reserve 改变当前vecotr所分配空间的大小

13.erase 删除指针指向的数据项

14.clear 清空当前的vector

15.rbegin 将vector反转后的开始指针返回(其实就是原来的end-1)

16.rend 将vector反转构的结束指针返回(其实就是原来的begin-1)

17.empty 判断vector是否为空

18.swap 与另一个vector交换数据


四、向量的基本操作

1>. a.size()                 //获取向量中的元素个数


    2>. a.empty()                //判断向量是否为空


    3>. a.clear()                //清空向量中的元素


    4>. 复制
        a = b ;            //将b向量复制到a向量中


    5>. 比较
        保持 ==、!=、>、>=、<、<= 的惯有含义 ;
        如: a == b ;    //a向量与b向量比较, 相等则返回1


    6>. 插入 - insert
        ①、 a.insert(a.begin(), 1000);            //将1000插入到向量a的起始位置前
        
        ②、 a.insert(a.begin(), 3, 1000) ;        //将1000分别插入到向量元素位置的0-2处(共3个元素)
        
        ③、 vector<int> a(5, 1) ;
            vector<int> b(10) ;
            b.insert(b.begin(), a.begin(), a.end()) ;        //将a.begin(), a.end()之间的全部元素插入到b.begin()前


    7>. 删除 - erase
        ①、 b.erase(b.begin()) ;                     //将起始位置的元素删除
        ②、 b.erase(b.begin(), b.begin()+3) ;        //将(b.begin(), b.begin()+3)之间的元素删除


    8>. 交换 - swap
        b.swap(a) ;            //a向量与b向量进行交换
1.push_back   在数组的最后添加一个数据
2.pop_back    去掉数组的最后一个数据 
3.at                得到编号位置的数据
4.begin           得到数组头的指针
5.end             得到数组的最后一个单元+1的指针
6.front        得到数组头的引用
7.back            得到数组的最后一个单元的引用
8.max_size     得到vector最大可以是多大
9.capacity       当前vector分配的大小
10.size           当前使用数据的大小
11.resize         改变当前使用数据的大小,如果它比当前使用的大,者填充默认值
12.reserve      改变当前vecotr所分配空间的大小
13.erase         删除指针指向的数据项
14.clear          清空当前的vector
15.rbegin        将vector反转后的开始指针返回(其实就是原来的end-1)
16.rend          将vector反转构的结束指针返回(其实就是原来的begin-1)
17.empty        判断vector是否为空
18.swap         与另一个vector交换数据
             vector<int> c.
                             c.clear()         移除容器中所有数据。
                             c.empty()         判断容器是否为空。
                             c.erase(pos)        删除pos位置的数据
                             c.erase(beg,end) 删除[beg,end)区间的数据
                             c.front()         传回第一个数据。
                             c.insert(pos,elem)  在pos位置插入一个elem拷贝
                             c.pop_back()     删除最后一个数据。
                             c.push_back(elem) 在尾部加入一个数据。
                             c.resize(num)     重新设置该容器的大小
                             c.size()         回容器中实际数据的个数。
                             c.begin()           返回指向容器第一个元素的迭代器
                             c.end()             返回指向容器最后一个元素的迭代器
1》使用reserve()函数提前设定容量大小,避免多次容量扩充操作导致效率低下。 

(1) size()告诉你容器中有多少元素。它没有告诉你容器为它容纳的元素分配了多少内存。 
(2) capacity()告诉你容器在它已经分配的内存中可以容纳多少元素。那是容器在那块内存中总共可以容纳多少元素,而不是还可以容纳多少元素。如果你想知道一个vector或string中有多少没有被占用的内存,你必须从capacity()中减去size()。如果size和capacity返回同样的值,容器中就没有剩余空间了,而下一次插入(通过insert或push_back等)会引发上面的重新分配步骤。 
(3) resize(Container::size_type n)强制把容器改为容纳n个元素。调用resize之后,size将会返回n。如果n小于当前大小,容器尾部的元素会被销毁。如果n大于当前大小,新默认构造的元素会添加到容器尾部。如果n大于当前容量,在元素加入之前会发生重新分配。 
(4) reserve(Container::size_type n)强制容器把它的容量改为至少n,提供的n不小于当前大小。这一般强迫进行一次重新分配,因为容量需要增加。(如果n小于当前容量,vector忽略它,这个调用什么都不做,string可能把它的容量减少为size()和n中大的数,但string的大小没有改变。在我的经验中,使用reserve来从一个string中修整多余容量一般不如使用“交换技巧”,那是条款17的主题。) 
这个简介表示了只要有元素需要插入而且容器的容量不足时就会发生重新分配(包括它们维护的原始内存分配和回收,对象的拷贝和析构和迭代器、指针和引用的失效)。所以,避免重新分配的关键是使用reserve尽快把容器的容量设置为足够大,最好在容器被构造之后立刻进行。 
例如,假定你想建立一个容纳1-1000值的vector。没有使用reserve,你可以像这样来做:

vector<int> v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);
  
  • 1
  • 2

在大多数STL实现中,这段代码在循环过程中将会导致2到10次重新分配。(10这个数没什么奇怪的。记住vector在重新分配发生时一般把容量翻倍,而1000约等于210。) 
把代码改为使用reserve,我们得到这个:

vector<int> v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);
  
  • 1
  • 2
  • 3

这在循环中不会发生重新分配。 

2》使用“交换技巧”来修整vector过剩空间/内存 
有一种方法来把它从曾经最大的容量减少到它现在需要的容量。这样减少容量的方法常常被称为“收缩到合适(shrink to fit)”。该方法只需一条语句:vector(ivec).swap(ivec); 
表达式vector(ivec)建立一个临时vector,它是ivec的一份拷贝:vector的拷贝构造函数做了这个工作。但是,vector的拷贝构造函数只分配拷贝的元素需要的内存,所以这个临时vector没有多余的容量。然后我们让临时vector和ivec交换数据,这时我们完成了,ivec只有临时变量的修整过的容量,而这个临时变量则持有了曾经在ivec中的没用到的过剩容量。在这里(这个语句结尾),临时vector被销毁,因此释放了以前ivec使用的内存,收缩到合适。 
3》用swap方法强行释放STL Vector所占内存

template < class T> void ClearVector( vector<T>& v )
{ 
    vector<T>vtTemp;
    vtTemp.swap( v );
} 
如 
    vector<int> v ;
    nums.push_back(1);
    nums.push_back(3);
    nums.push_back(2);
    nums.push_back(4);
    vector<int>().swap(v);
/* 或者v.swap(vector<int>()); */
/*或者{ std::vector<int> tmp = v;   v.swap(tmp);   }; //加大括号{ }是让tmp退出{ }时自动析构*/

6.vector的其他成员函数

   c.assign(beg,end):将[beg; end)区间中的数据赋值给c。
        c.assign(n,elem):将n个elem的拷贝赋值给c。 
        c.at(idx):传回索引idx所指的数据,如果idx越界,抛出out_of_range。 
        c.back():传回最后一个数据,不检查这个数据是否存在。
        c.front():传回地一个数据。 
        get_allocator:使用构造函数返回一个拷贝。 
        c.rbegin():传回一个逆向队列的第一个数据。 
        c.rend():传回一个逆向队列的最后一个数据的下一个位置。 
        c.~ vector <Elem>():销毁所有数据,释放内存。    

7.备注:在用vector的过程中的一些问题,特此列出讨论:

1)
vector <int > a;
int b = 5;
a.push_back(b);
此时若对b另外赋值时不会影响a[0]的值
2)
vector <int*> a;
int *b;
b= new int[4];
b[0]=0;
b[1]=1;
b[2]=2;
a.push_back(b);
delete b; //释放b的地址空间
for(int i=0 ; i <3 ; i++)
{
cout<<a[0][i]<<endl;
}


8、vector查找指定元素并删除 

查找时可以使用find函数,此时必须将algorithm头文件包含进去。 
查找完成后,如果vector中包含该元素,则返回第一个元素,或者超出末端的下一个位置,返回的是迭代器。 
删除元素之前,必须确保返回的不是end迭代器。

#include <iostream>  
#include <vector>  
#include <algorithm>  

using namespace std;  

void print(vector<int> v){  
    vector<int>::iterator iter=v.begin();  
    while(iter!=v.end())  
        cout<<*iter++<<" ";  
    cout<<endl;  
}  

int main(int argc,char** argv){  
    int arr[]={1,2,3,4,5,6,7,8,9};  

    //vector初始化  
    vector<int> v(arr,arr+sizeof(arr)/sizeof(*arr));  
    print(v);  

    //在vector中查找指定元素  
    vector<int>::iterator iter=find(v.begin(),v.end(),5);  

    //删除指定元素  
    if(iter!=v.end())v.erase(iter);  

    print(v);  

    return 0;  
}  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

9、在vector中查找元素及其位置

#include <iostream>  
#include <vector>  
#include <algorithm>  

using namespace std;  
int _tmain()  
{  
     vector <int> vecIntegerArray;  
     vecIntegerArray.push_back(50);  
     vecIntegerArray.push_back(222);  
     vecIntegerArray.push_back(3);  
     vecIntegerArray.push_back(44);  

     cout<< "the contents of the vector are: " << endl;  
     vector <int>::iterator iArrayWalker = vecIntegerArray.begin();  
     while(iArrayWalker != vecIntegerArray.end())  
     {     
          cout << *iArrayWalker << endl;  
          iArrayWalker++;  
     }  
     vector <int>::iterator iElement = find(vecIntegerArray.begin(),  
                           vecIntegerArray.end(),3);  
     if( iElement != vecIntegerArray.end() )  
     {  
          int nPosition = distance(vecIntegerArray.begin(),iElement);  
          cout << "Value  "<< *iElement;  
          cout <<"  find in the vector at position: " <<nPosition + 1 <<endl;  
     }  
     getchar();  
     return 0 ;  
}  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

10、C++ Vector 最大 最小值 索引 位置 

使用STL的Vector时,利用函数 max_element,min_element,distance可以获取Vector中最大、最小值的值和位置索引: 
参考: http://stackoverflow.com/questions/2953491/finding-the-position-of-the-max-element 
代码:

#include <vector>  
#include <algorithm>  
#include <iostream>  

int main()  
{  
    std::vector<double> v {1.0, 2.0, 3.0, 4.0, 5.0, 1.0, 2.0, 3.0, 4.0, 5.0};  

    std::vector<double>::iterator biggest = std::max_element(std::begin(v), std::end(v));  
    std::cout << "Max element is " << *biggest<< " at position " << std::distance(std::begin(v), biggest) << std::endl;  

    auto smallest = std::min_element(std::begin(v), std::end(v));  
    std::cout << "min element is " << *smallest<< " at position " << std::distance(std::begin(v), smallest) << std::endl;  
}  


输出:  

Max element is 5 at position 4  
min element is 1 at position 0  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
#include <vector>  
#include <algorithm>  
class student  
{  
    int NO;  
    AnsiString strName;  
    int grade;  
    public:  
    student(int NO,AnsiString strName,int grade)  
    {  
       this->NO = NO;  
       this->strName = strName;  
       this->grade   = grade;  
    }  
    bool operator==(AnsiString strName)  
    {  
       return this->strName == strName;  
    }  
};  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

上面这个类,在STL中叫函数对象,重载运算符==,当执行Count函数时,会比较[v.begin,v.end]中的各 
student对象是否与“张三”相等

void __fastcall TForm1::Button11Click(TObject *Sender)  
{  
    vector<student> v;  
    student s1(1000,AnsiString("张三"),90);  
    student s2(1001,AnsiString("张三"),91);  
    student s3(1002,AnsiString("王五"),90);  
    student s4(1003,AnsiString("赵六"),90);  
    v.push_back(s1);  
    v.push_back(s2);  
    v.push_back(s3);  
    v.push_back(s4);  
    int nCount = count(v.begin(),v.end(),"张三");  
    ShowMessage(nCount);  

}  

四、基本用法

#include < vector> 
using namespace std;

五、简单介绍

  1. Vector<类型>标识符
  2. Vector<类型>标识符(最大容量)
  3. Vector<类型>标识符(最大容量,初始所有值)
  4. Int i[5]={1,2,3,4,5} 
    Vector<类型>vi(i,i+2);//得到i索引值为3以后的值
  5. Vector< vector< int> >v; 二维向量//这里最外的<>要有空格。否则在比较旧的编译器下无法通过


1.pop_back()&push_back(elem)实例在容器最后移除和插入数据

#include < string.h > #include < vector > #include < iostream > using namespace std ; int main ( ) { vector < int > obj ; //创建一个向量存储容器 int for ( int i = 0 ; i < 10 ; i ++ ) // push_back(elem)在数组最后添加数据 { obj . push_back ( i ) ; cout << obj [ i ] << " , " ; } for ( int i = 0 ; i < 5 ; i ++ ) //去掉数组最后一个数据 { obj . pop_back ( ) ; } cout << " \ n " << endl ; for ( int i = 0 ; i < obj . size ( ) ; i ++ ) //size()容器中实际数据个数 { cout << obj [ i ] << " , " ; } return 0 ; }

输出结果为:

0,1,2,3,4,5,6,7,8,9,

0,1,2,3,4,

2.clear()清除容器中所以数据

#include < string.h > #include < vector > #include < iostream > using namespace std ; int main ( ) { vector < int > obj ; for ( int i = 0 ; i < 10 ; i ++ ) //push_back(elem)在数组最后添加数据 { obj . push_back ( i ) ; cout << obj [ i ] << " , " ; } obj . clear ( ) ; //清除容器中所以数据 for ( int i = 0 ; i < obj . size ( ) ; i ++ ) { cout << obj [ i ] << endl ; } return 0 ; }

输出结果为:

0,1,2,3,4,5,6,7,8,9,

3.排序

#include < string.h > #include < vector > #include < iostream > #include < algorithm > using namespace std ; int main ( ) { vector < int > obj ; obj . push_back ( 1 ) ; obj . push_back ( 3 ) ; obj . push_back ( 0 ) ; sort ( obj . begin ( ) , obj . end ( ) ) ; //从小到大 cout << " 从小到大: " << endl ; for ( int i = 0 ; i < obj . size ( ) ; i ++ ) { cout << obj [ i ] << " , " ; } cout << " \ n " << endl ; cout << " 从大到小: " << endl ; reverse ( obj . begin ( ) , obj . end ( ) ) ; //从大到小 for ( int i = 0 ; i < obj . size ( ) ; i ++ ) { cout << obj [ i ] << " , " ; } return 0 ; }

输出结果为:

从小到大:
0,1,3,

从大到小:
3,1,0,

1.注意 sort 需要头文件 #include <algorithm>

2.如果想 sort 来降序,可重写 sort

bool compare(int a,int b) 
{ 
    return a< b; //升序排列,如果改为return a>b,则为降序 
} 
int a[20]={2,4,1,23,5,76,0,43,24,65},i; 
for(i=0;i<20;i++) 
    cout<< a[i]<< endl; 
sort(a,a+20,compare);

4.访问(直接数组访问&迭代器访问)

#include < string.h > #include < vector > #include < iostream > #include < algorithm > using namespace std ; int main ( ) { //顺序访问 vector < int > obj ; for ( int i = 0 ; i < 10 ; i ++ ) { obj . push_back ( i ) ; } cout << " 直接利用数组: " ; for ( int i = 0 ; i < 10 ; i ++ ) //方法一 { cout << obj [ i ] << " " ; } cout << endl ; cout << " 利用迭代器: " ; //方法二,使用迭代器将容器中数据输出 vector < int >:: iterator it ; //声明一个迭代器,来访问vector容器,作用:遍历或者指向vector容器的元素 for ( it = obj . begin ( ) ; it != obj . end ( ) ; it ++ ) { cout <<* it << " " ; } return 0 ; }

输出结果为:

直接利用数组:0 1 2 3 4 5 6 7 8 9 
利用迭代器:0 1 2 3 4 5 6 7 8 9

5.二维数组两种定义方法(结果一样)

方法一

#include < string.h > #include < vector > #include < iostream > #include < algorithm > using namespace std ; int main ( ) { int N = 5 , M = 6 ; vector < vector < int > > obj ( N ) ; //定义二维动态数组大小5行 for ( int i = 0 ; i < obj . size ( ) ; i ++ ) //动态二维数组为5行6列,值全为0 { obj [ i ] . resize ( M ) ; } for ( int i = 0 ; i < obj . size ( ) ; i ++ ) //输出二维动态数组 { for ( int j = 0 ; j < obj [ i ] . size ( ) ; j ++ ) { cout << obj [ i ] [ j ] << " " ; } cout << " \ n " ; } return 0 ; }

方法二

#include < string.h > #include < vector > #include < iostream > #include < algorithm > using namespace std ; int main ( ) { int N = 5 , M = 6 ; vector < vector < int > > obj ( N , vector < int > ( M ) ) ; //定义二维动态数组5行6列 for ( int i = 0 ; i < obj . size ( ) ; i ++ ) //输出二维动态数组 { for ( int j = 0 ; j < obj [ i ] . size ( ) ; j ++ ) { cout << obj [ i ] [ j ] << " " ; } cout << " \ n " ; } return 0 ; }

输出结果为:

0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 
0 0 0 0 0 0 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值