C++ vector用法(详解!!函数,实现)

原创 2016年09月30日 01:13:40
  • 7862

1,简述一下vector的基本操作,它的size,capacity(),clear,reverse,reserve,

  push_back等!!!

2,说说,vector的存储特性,是顺序存储还是如同链表般,如果是顺序存储的话,那么是如何执行

  erase,insert等函数,???(假如后面的空间不够的话,我们需要合理的算法来重新找出一块

  相应的空间吗???拷贝,回收吗???是不是特别麻烦),如果是链式存储的话,那么它又是如何做到快速

  的访问的(通过下标来的)!!!

1 基本操作

(1)头文件#include<vector>.

(2)创建vector对象,vector<int> vec;

(3)尾部插入数字:vec.push_back(a);

(4)使用下标访问元素,cout<<vec[0]<<endl;记住下标是从0开始的。

(5)使用迭代器访问元素.

  1. <span style="font-size:18px;">vector<int>::iterator it;
  2. for(it=vec.begin();it!=vec.end();it++)
  3. cout<<*it<<endl;</span>

(6)插入元素:    vec.insert(vec.begin()+i,a);在第i个元素后面插入a;

(7)删除元素:    vec.erase(vec.begin()+2);删除第3个元素

        vec.erase(vec.begin()+i,vec.end()+j);删除区间[i,j-1];区间从0开始

(8)向量大小:vec.size();

(9)清空:vec.clear()   //清空之后,vec.size()为0

一个简单的程序:

  1. <span style="font-size:18px;">#include<stdio.h>
  2. #include<vector>
  3. #include<iostream>
  4. using namespace std;
  5. int main()
  6. {
  7. int i=0;
  8. vector<int> vec;
  9. for(i=0; i<10; i++)
  10. {
  11. vec.push_back(i);   //10个元素依次进入,结果为10
  12. }
  13. for(unsigned int i=0; i<vec.size(); i++)
  14. {
  15. cout<<"初始化遍历:"<<vec[i]<<endl;
  16. }
  17. //结果为:0,1,2,3,4,5,6,7,8,9
  18. vector<int>::iterator it;
  19. for(it = vec.begin(); it!=vec.end(); it++)
  20. {
  21. cout<<"迭代遍历:"<<*it<<endl;
  22. }
  23.   //结果为:0,1,2,3,4,5,6,7,8,9
  24.    vec.insert(vec.begin()+4,0);
  25.   //结果为:11
  26. for(unsigned int i=0; i<vec.size(); i++)
  27. {
  28. cout<<"插入遍历:"<<vec[i]<<endl;
  29. }
  30. //结果为:0,1,2,3,0,4,5,6,7,8,9
  31. vec.erase(vec.begin()+2);
  32. for(unsigned int i=0; i<vec.size(); i++)
  33. {
  34. cout<<"擦除遍历:"<<vec[i]<<endl;
  35. }
  36.   //结果为:0,1,3,0,4,5,6,7,8,9
  37. vec.erase(vec.begin()+3,vec.begin()+5);
  38.   
  39. for(vector<int>::iterator it = vec.begin(); it!=vec.end(); it++)
  40. {
  41. cout<<"迭代遍历:"<<*it<<endl;
  42. }
  43. return 0;
  44. }
  45. </span>

2:

vector的元素不仅仅可以使int,double,string,还可以是结构体,但是要注意:结构体要定义为全局的,否则会出错。下面是一段简短的程序代码:

  1. <span style="font-size:18px;">#include<stdio.h>
  2. #include<algorithm>
  3. #include<vector>
  4. #include<iostream>
  5. using namespace std;
  6. typedef struct rect
  7. {
  8. int id;
  9. int length;
  10. int width;
  11.   //对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
  12.   bool operator< (const rect &a)  const
  13. {
  14. if(id!=a.id)
  15. return id<a.id;
  16. else
  17. {
  18. if(length!=a.length)
  19. return length<a.length;
  20. else
  21. return width<a.width;
  22. }
  23. }
  24. }Rect;
  25. int main()
  26. {
  27. vector<Rect> vec;
  28. Rect rect;
  29. rect.id=1;
  30. rect.length=2;
  31. rect.width=3;
  32. vec.push_back(rect);
  33. vector<Rect>::iterator it=vec.begin();
  34. cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl;
  35. return 0;
  36. }</span>

3  算法

(1) 使用reverse将元素翻转:需要头文件#include<algorithm>

reverse(vec.begin(),vec.end());将元素翻转(在vector中,如果一个函数中需要两个迭代器,

一般后一个都不包含.)

(2)使用sort排序:需要头文件#include<algorithm>,

sort(vec.begin(),vec.end());(默认是按升序排列,即从小到大).

可以通过重写排序比较函数按照降序比较,如下:

定义排序比较函数:

bool Comp(const int &a,const int &b)
{
    return a>b;
}
调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。

vector : C++ STL中的顺序容器,封装数组

1. vector容器的内存自增长

与其他容器不同,其内存空间只会增长,不会减小。先来看看"C++ Primer"中怎么说:为了支持快速的随机访

问,vector容器的元素以连续方式存放,每一个元素都紧挨着前一个元素存储。设想一下,当vector添加一个元素时,

为了满足连续存放这个特性,都需要重新分配空间、拷贝元素、撤销旧空间,这样性能难以接受。因此STL实现者在对

vector进行内存分配时,其实际分配的容量要比当前所需的空间多一些。就是说,vector容器预留了一些额外的存储

区,用于存放新添加的元素,这样就不必为每个新元素重新分配整个容器的内存空间。

关于vector的内存空间,有两个函数需要注意:size()成员指当前拥有的元素个数;capacity()成员指当前(容器必须分

配新存储空间之前)可以存储的元素个数。reserve()成员可以用来控制容器的预留空间。vector另外一个特性在于它的

内存空间会自增长,每当vector容器不得不分配新的存储空间时,会以加倍当前容量的分配策略实现重新分配。例如,

当前capacity为50,当添加第51个元素时,预留空间不够用了,vector容器会重新分配大小为100的内存空间,作为新

连续存储的位置。

  1. <span style="font-size:18px;">#include <iostream>
  2. using namespace std;
  3. #include <vector>
  4. int main()
  5. {
  6. vector<int> arry;
  7. //arry.reserve(10);
  8. cout << arry.capacity() <<endl;
  9. arry.push_back(1);
  10. cout<<arry.capacity() <<endl;
  11. arry.push_back(2);
  12. cout<<arry.capacity() <<endl;
  13. arry.push_back(3);
  14. cout<<arry.capacity() <<endl;
  15. }
  16. </span>

运行结果:

当我们将上面的那句注释去掉之后:

2. vector内存释放

由于vector的内存占用空间只增不减,比如你首先分配了10,000个字节,然后erase掉后面9,999个,留下一个有效元素,但是内存占

用仍为10,000个。所有内存空间是在vector析构时候才能被系统回收。empty()用来检测容器是否为空的,clear()可以清空所有元素。

但是即使clear(),vector所占用的内存空间依然如故,无法保证内存的回收。

如果需要空间动态缩小,可以考虑使用deque。如果非vector不可,可以用swap()来帮助你释放内存。具体方法如下:

  1. <span style="font-size:18px;">vector<int> nums;
  2. nums.push_back(1);
  3. nums.push_back(1);
  4. nums.push_back(2);
  5. nums.push_back(2);
  6. vector<int>().swap(nums); //或者nums.swap(vector<int> ())</span>

或者如下所示,使用一对大括号,意思一样的:

  1. <span style="font-size:18px;">//加一对大括号是可以让tmp退出{}的时候自动析构
  2. {
  3. std::vector<int> tmp =   nums;
  4. nums.swap(tmp);
  5. }
  6. </span>

swap()是交换函数,使vector离开其自身的作用域,从而强制释放vector所占的内存空间,总而言之,释放vector内存最简单的方法是vector<int>.swap(nums)。当时如果nums是一个类的成员,不能把vector<int>.swap(nums)写进类的析构函数中,否则会导致double free or corruption (fasttop)的错误,原因可能是重复释放内存。标准解决方法如下:

  1. <span style="font-size:18px;">template < class T >
  2. void ClearVector( vector< T >& vt )
  3. {
  4. vector< T > vtTemp;
  5. veTemp.swap( vt );
  6. }</span>

3. 利用vector释放指针

如果vector中存放的是指针,那么当vector销毁时,这些指针指向的对象不会被销毁,那么内存就不会被释放。如下面这种情况,vector中的元素时由new操作动态申请出来的对象指针:

  1. <span style="font-size:18px;">#include <vector>
  2. using namespace std;
  3. vector<void *> v;</span>

每次new之后调用v.push_back()该指针,在程序退出或者根据需要,用以下代码进行内存的释放:

  1. <span style="font-size:18px;">for (vector<void *>::iterator it = v.begin(); it != v.end(); it ++)
  2. if (NULL != *it)
  3. {
  4. delete *it;
  5. *it = NULL;
  6. }
  7. v.clear();</span>

3,

vector是线性容器,它的元素严格的按照线性序列排序,和动态数组很相似,和数组一样,它的元素存储在一块连续的存储空间中,这也意味着我们不仅可以使用迭代器(iterator)访问元素,还可以使用指针的偏移方式访问,和常规数组不一样的是,vector能够自动存储元素,可以自动增长或缩小存储空间,

vector的优点:

1.       可以使用下标访问个别的元素

2.       迭代器可以按照不同的方式遍历容器

3.       可以在容器的末尾增加或删除元素

和数组相比,虽然容器在自动处理容量的大小时会消耗更多的内存,但是容器能提供和数组一样的性能,而且能很好的调整存储空间大小

和其他标准的顺序容器相比(deques or lists),能更有效访问容器内的元素和在末尾添加和删除元素,在其他位置添加和删除元素,vector则不及其他顺序容器,在迭代器和引用也不比lists支持的好

容器的大小和容器的容量是有区别的,大小是指元素的个数,容量是分配的内存大小,容量一般等于或大于容器的大小,vector::size()返回容器的大小,vector::capacity()返回容量值,容量多于容器大小的部分用于以防容器的增加使用,每次重新分配内存都会很影响程序的性能,所以一般分配的容量大于容器的大小,若要自己指定分配的容量的大小,则可以使用vector::reserve(),但是规定的值要大于size()值,

1.构造和复制构造函数

explicit vector ( const Allocator& = Allocator() );

explicit vector ( size_type n, const T& value= T(), const Allocator& = Allocator() );

template <class InputIterator>

vector ( InputIterator first, InputIterator last, const Allocator& = Allocator() );

vector ( const vector<T,Allocator>& x );

explicit:是防止隐式转换, Allocator是一种内存分配模式,一般是使用默认的

vector<int> A;  //创建一个空的的容器

vector<int> B(10,100); //创建一个个元素,每个元素值为

vector<int> C(B.begin(),B.end()); //使用迭代器,可以取部分元素创建一个新的容器

vector<int> D(C); //复制构造函数,创建一个完全一样的容器

2.析构函数

~vector()

销毁容器对象并回收了所有分配的内存

3.重载了=符号

vector<int> E;

E = B; //使用=符号

B = vector<int>(); //将B置为空容器

4. vector::begin()  返回第一个元素的迭代器

函数原型:

iterator begin ();  //返回一个可变迭代器

const_iterator begin () const; //返回一个常量的迭代器,不可变

5.vector::end()  返回的是越界后的第一个位置,也就是最后一个元素的下一个位置

iterator end ();

const_iterator end () const;

6.vector::rbegin() 反序的第一个元素,也就是正序最后一个元素

reverse_iterator rbegin();

const_reverse_iterator rbegin() const;

7.vector::rend() 反序的最后一个元素下一个位置,也相当于正序的第一个元素前一个位置

reverse_iterator rend();

const_reverse_iterator rend() const;

和vector::end()原理一样

8.vector::size() 返回容器中元素个数

size_type size() const;

注意与vector::capacity()的区别

9.vector::max_size()

size_type max_size () const;

返回容器的最大可以存储的元素个数,这是个极限,当容器扩展到这个最大值时就不能再自动增大

10. vector::resize()

void resize ( size_type sz, T c = T() );

重新分配容器的元素个数,这个还可以改容器的容量,如果重新分配的元素个数比原来的小,将截断序列,后面的部分丢弃,如果大于原来的个数,后面的值是c的值,默认为0

11. vector::capacity()

size_type capacity () const;

返回vector的实际存储空间的大小,这个一般大于或等于vector元素个数,注意与size()函数的区别

12. vector::empty()

bool empty () const;

当元素个数为0时返回true,否则为false,根据的是元素个数而不是容器的存储空间的大小

13. vector::reserve()

void reserve ( size_type n );

重新分配空间的大小,不过这个n值要比原来的capacity()返回的值大,不然存储空间保持不变,n值要比原来的实际存储空间大才能重新分配空间,但是最大值不可以大于max_size的值,否则会抛出异常

14. vector::operator[]  //重载了[]符号

reference  operator[] ( size_type n );

const_reference  operator[] ( size_type n ) const;

实现了下标访问元素

15. vector::at()

const_reference at ( size_type n ) const;

reference at ( size_type n );

在函数的操作方面和下标访问元素一样,不同的是当这个函数越界时会抛出一个异常out_of_range

16. vector::front()

reference front ( );

const_reference front ( ) const;

返回第一个元素的值,与begin()函数有区别,begin()函数返回的是第一个元素的迭代器

17. vector::back()

reference back ( );

const_reference back ( ) const;

同样,返回最后一个元素的值,注意与end()函数的区别

18. vector::assign()

template <class InputIterator> void assign ( InputIterator first, InputIterator last );

void assign ( size_type n, const T& u );

将丢弃原来的元素然后重新分配元素,第一个函数是使用迭代器,第二个函数是使用n个元素,每个元素的值为u。

19. vector::push_back()

void push_back ( const T& x );

在容器的最后一个位置插入元素x,如果size值大于capacity值,则将重新分配空间

20. vector::pop_back()

void pop_back ( );

删除最后一个元素

21. vector::insert()

iterator insert ( iterator position, const T& x );

void insert ( iterator position, size_type n, const T& x );

template <class InputIterator>

void insert ( iterator position, InputIterator first, InputIterator last );

插入新的元素,

第一个函数,在迭代器指定的位置前插入值为x的元素

第二个函数,在迭代器指定的位置前插入n个值为x的元素

第三个函数,在迭代器指定的位置前插入另外一个容器的一段序列迭代器first到last

若插入新的元素后总得元素个数大于capacity,则重新分配空间

22. vector::erase()

iterator erase ( iterator position );

iterator erase ( iterator first, iterator last );

删除元素或一段序列

23. vector::swap()

void swap ( vector<T,Allocator>& vec );

交换这两个容器的内容,这涉及到存储空间的重新分配

24. vector::clear()

void clear ( );

将容器里的内容清空,size值为0,但是存储空间没有改变

  1. <span style="font-size:18px;">#include <vector>
  2. #include <iostream>
  3. using namespace std;
  4. int _tmain(int argc, _TCHAR* argv[])
  5. {
  6. //构造函数,复制构造函数(元素类型要一致),
  7. vector<int> A;  //创建一个空的的容器
  8. vector<int> B(10,100); //创建一个10个元素,每个元素值为100
  9. vector<int> C(B.begin(),B.end()); //使用迭代器,可以取部分元素创建一个新的容器
  10. vector<int> D(C); //复制构造函数,创建一个完全一样的容器
  11. //重载=
  12. vector<int> E;
  13. E = B;
  14. //vector::begin(),返回的是迭代器
  15. vector<int> F(10); //创建一个有10个元素的容器
  16. for (int i = 0; i < 10; i++)
  17. {
  18. F[i] = i;
  19. }
  20. /*
  21. vector<int> F; //创建一个空容器
  22. for (int i = 0; i < 10; i++)
  23. {
  24. F.push_back(i);
  25. }
  26. */
  27. vector<int>::iterator BeginIter = F.begin();
  28. cout << *BeginIter << endl; //输出0
  29. //vector::end() 返回迭代器
  30. vector<int>::iterator EndIter = F.end();
  31. EndIter--; //向后移一个位置
  32. cout << *EndIter << endl; //输出9
  33. //vector::rbegin() 返回倒序的第一个元素,相当于最后一个元素
  34. vector<int>::reverse_iterator ReverBeIter = F.rbegin();
  35. cout << *ReverBeIter << endl; //输出9
  36. //vector::rend() 反序的最后一个元素下一个位置,也相当于正序的第一个元素前一个位置
  37. vector<int>::reverse_iterator ReverEnIter = F.rend();
  38. ReverEnIter--;
  39. cout << *ReverEnIter << endl; //输出0
  40. //vector::size() 返回元素的个数
  41. cout << F.size() << endl; //输出10
  42. //vector::max_size()
  43. cout << F.max_size() << endl; //输出1073741823,这个是极限元素个数
  44. //vector::resize()
  45. cout << F.size() << endl; //输出10
  46. F.resize(5);
  47. for(int k = 0; k < F.size(); k++)
  48. cout << F[k] << "  "; //输出 0 1 2 3 4
  49. cout << endl;
  50. //vector::capacity()
  51. cout << F.size() << endl; //5
  52. cout << F.capacity() << endl; //10
  53. //vector::empty()
  54. B.resize(0);
  55. cout << B.size() << endl; //0
  56. cout << B.capacity() << endl; //10
  57. cout << B.empty() << endl; //true
  58. //vector::reserve() //重新分配存储空间大小
  59. cout << C.capacity() << endl; //10
  60. C.reserve(4);
  61. cout << C.capacity() << endl; //10
  62. C.reserve(14);
  63. cout << C.capacity() << endl; //14
  64. //vector::operator []
  65. cout << F[0] << endl; //第一个元素是0
  66. //vector::at()
  67. try
  68. {
  69. cout << "F.size = " << F.size() << endl; //5
  70. cout << F.at(6) << endl; //抛出异常
  71. }
  72. catch(out_of_range)
  73. {
  74. cout << "at()访问越界" << endl;
  75. }
  76. //vector::front() 返回第一个元素的值
  77. cout << F.front() << endl; //0
  78. //vector::back()
  79. cout << F.back() << endl; //4
  80. //vector::assign()
  81. cout << A.size() << endl; //0
  82. vector<int>::iterator First = C.begin();
  83. vector<int>::iterator End = C.end()-2;
  84. A.assign(First,End);
  85. cout << A.size() << endl; //8
  86. cout << A.capacity() << endl; //8
  87. A.assign(5,3); //将丢弃原来的所有元素然后重新赋值
  88. cout << A.size() << endl; //5
  89. cout << A.capacity() << endl; //8
  90. //vector::push_back()
  91. cout << *(F.end()-1) << endl; //4
  92. F.push_back(100);
  93. cout << *(F.end()-1) << endl; //100
  94. //vector::pop_back()
  95. cout << *(F.end()-1) << endl; //100
  96. F.pop_back();
  97. cout << *(F.end()-1) << endl; //4
  98. //vector::swap()
  99. F.swap(D); //交换这两个容器的内容
  100. for(int f = 0; f < F.size(); f++)
  101. cout << F[f] << " ";
  102. cout << endl;
  103. for (int d = 0; d < D.size(); d++)
  104. cout << D[d] << " ";
  105. cout << endl;
  106. //vector::clear()
  107. F.clear();
  108. cout << F.size() << endl;     //0
  109. cout << F.capacity() << endl; //10
  110. return 0;
  111. }
  112. </span>

11-vector的使用的更多相关文章

  1. C++11 vector使用emplace_back代替push_back

    C++11中,针对顺序容器(如vector.deque.list),新标准引入了三个新成员:emplace_front.emplace和emplace_back,这些操作构造而不是拷贝元素.这些操作分 ...

  2. STL学习二:Vector容器

    1.Vector容器简介 vector是将元素置于一个动态数组中加以管理的容器. vector可以随机存取元素(支持索引值直接存取, 用[]操作符或at()方法,这个等下会详讲). vector尾部添 ...

  3. vector 内部方法大全 学习(初学者的参考资料)

    1    vector构造函数:也就是如何对一个vector对象进行初始化 ////////////////////////////代码//////////////////////////////// ...

  4. vector的成员函数解析

    vector是线性容器,它的元素严格的依照线性序列排序,和动态数组非常相似,和数组一样,它的元素存储在一块连续的存储空间中,这也意味着我们不仅能够使用迭代器(iterator)訪问元素,还能够使用指针 ...

  5. vector成员函数解析

    vector线性集装箱,其元素颜格排序根据线性序列,和动态数组很阶段似,像阵列,它的元素被存储在连续的存储空间,这也意味着,我们不仅能够使用迭代器(iterator)访问元素,也可以用一个指针访问偏移 ...

  6. C++标准库之vector(各函数及其使用全)

    原创作品,转载请注明出处:http://www.cnblogs.com/shrimp-can/p/5280566.html iterator类型: iterator:到value_type的访问,va ...

  7. C++模板之Vector与STL初探

    STL源码初步接触 STL = Standard Template Library,直译过来是:标准模板库,是惠普实验室开发的一系列软件的统称.从根本上说,STL是一些"容器"的集 ...

  8. C++11 带来的新特性 (1)

    1 语法改进 1.1 模板表达式中的空格 在c++03 及以前 vector<list<int>>; //Error vector<list<int> > ...

  9. Vector源码解析

    概要 学完ArrayList和LinkedList之后,我们接着学习Vector.学习方式还是和之前一样,先对Vector有个整体认识,然后再学习它的源码:最后再通过实例来学会使用它.第1部分 Vec ...

  10. c++ primer 11 泛型算法

    使用泛型算法必须包含头文件#inlucde <algorithm> 标准库还定义一组泛化的算术算法,其命名习惯与泛型算法相同,包含头文件#include <numeric> f ...

随机推荐

  1. Lua编程

    lua编程大杂烩.博客其他方面也不错.先记录.http://www.cnblogs.com/stephen-liu74/category/360139.html

  2. linux C使用strerror来追查错误信息

    最近工作中有个需求:程序将文件进行处理,然后将处理完毕的文件挪走.我用了rename函数来挪动文件,可是在docker化的环境中,文件却无法挪动.不知道什么原因.现在,对程序进行调整,如果rename ...

  3. 抛弃Https让Cas以Http协议提供单点登录服务

    本文环境: 1.apache-tomcat-7.0.50-windows-x86 2.cas-server-3.4.11 3.cas-client-3.2.1 将cas-server-webapp-3 ...

  4. jQuery的ajax跨域实现

    今天有人问我跨域ajax请求是否可以发送,之前没接触过此类问题,没答上,后来查了下,以下备忘. 我在本地建了三个站点,并设置了host文件模拟跨子域和跨全域 coolkissbh.com blog.c ...

  5. mysql链接出现10060

    http://www.cnblogs.com/meetrice/p/5309666.html 使用navicate链接 http://www.cnblogs.com/cxint/p/7454054.h ...

  6. shell编程中用户输入处理(shell 04)

    shell编程中用户输入处理1.命令行参数2.脚本运行时获取输入 命令行参数 通过空格来进行分割的位置参数 :$+position $0,$1,$2 ....$0 :程序名$1,$2,$3 ... $ ...

  7. SCSI, (P)ATA, SAS, NL-SAS and SATA, what’s the difference?

    Everybody needs storage space nowadays. Whether it is used for high performance computing or simply ...

  8. 使用Spring和Tomcat发布CXF SOAP WebService

    上一节中使用代理工厂JaxWsProxyFactoryBean来发布WebService, 这种方式必须指定运行的端口,如果端口被占用,就会发布失败. cxf的WebService也可利用Tomcat ...

  9. Quartz.net 2.x 学习笔记01

    Quartz.net 2.0 2012年4月9日发布了Released版本,到目前(2014-12-08)为止是2.3版 Quartz.net 项目地址:http://www.quartz-sched ...

  10. Mongodb3.0 新增用户身份验证db.createUser()

    定义:创建一个数据库新用户用db.createUser()方法,如果用户存在则返回一个用户重复错误. 语法:db.createUser(user, writeConcern)    user这个文档创 ...