参考内容来源1:https://www.cnblogs.com/mengfanrong/p/3770971.html?tdsourcetag=s_pcqq_aiomsg
参考内容来源2:https://www.runoob.com/w3cnote/cpp-vector-container-analysis.html

标准库vector类型使用须要的头文件:#include 。vector 是一个类模板。不是一种数据类型,vector是一种数据类型。vector的存储空间是连续的,list不是。

一、 定义和初始化
1.vector< typeName > v1; //默认v1为空,故以下的赋值是错误的:v1[0]=5;
2.vectorv2(v1); 或vectorv2=v1;或vector v2(v1.begin(), v1.end()); //v2是v1的一个副本,若v1.size()>v2.size()则赋值后v2.size()被扩充为v1.size()。
3.vector< typeName > v3(n,i); //v3包括n个值为i的typeName类型元素
4.vector< typeName > v4(n); //v4含有n个值为0的元素
5.int a[4]={0,1,2,3,3}; vector v5(a,a+5); //v5的size为5,v5被初始化为a的5个值。后一个指针要指向将被拷贝的末元素的下一位置。

二、 值初始化
1> 假设没有指定元素初始化式,标准库自行提供一个初始化值进行值初始化。
2> 假设保存的式含有构造函数的类类型的元素,标准库使用该类型的构造函数初始化。
3> 假设保存的式没有构造函数的类类型的元素,标准库产生一个带初始值的对象,使用这个对象进行值初始化。

三、vector对象最重要的几种操作

  1. v.push_back(t) 在容器的最后加入一个值为t的数据,容器的size变大。
    另外list有push_front()函数,在前端插入,后面的元素下标依次增大。
  2. v.size() 返回容器中数据的个数,size返回对应vector类定义的size_type的值。
  3. v.empty() 推断vector是否为空
  4. v[n] 返回v中位置为n的元素
  5. v.insert(pointer,number, content) 向v中pointer指向的位置插入number个content的内容。
    还有v. insert(pointer, content),v.insert(pointer,a[2],a[4])将a[2]到a[4]三个元素插入。
  6. v.pop_back() 删除容器的末元素,并不返回该元素。
  7. v.erase(pointer1,pointer2) 删除pointer1到pointer2中间(包含pointer1所指)的元素。
    vector中删除一个元素后,此位置以后的元素都须要往前移动一个位置,尽管当前迭代器位置没有自己主动加1,可是因为元素的顺次前移,也就相当于迭代器的自己主动指向下一个位置一样。
  8. v1==v2 推断v1与v2是否相等。
  9. !=、<、<=、>、>= 保持这些操作符惯有含义。
  10. vector::iterator p=v1.begin( ); p初始值指向v1的第一个元素。*p取所指向元素的值。对于const vector仅仅能用vector::const_iterator类型的指针訪问。
  11. p=v1.end( ); p指向v1的最后一个元素的下一位置。
  12. 12.v.clear() 删除容器中的全部元素。

#include中的泛函算法
搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if()
分类排序:sort() 、merge()
删除算法:unique() 、remove()
生成和变异:generate() 、fill() 、transformation() 、copy()
关系算法:equal() 、min() 、max()

四、内存管理与效率

1.使用reserve()函数提前设定容量大小,避免多次容量扩充操作导致效率低下。

关于STL容器,最令人称赞的特性之中的一个就是是仅仅不超过它们的最大大小,它们就能够自己主动增长到足以容纳你放进去的数据。(要知道这个最大值,仅仅要调用名叫max_size的成员函数。)对于vector和string,假设须要很多其它空间,就以相似realloc的思想来增长大小。vector容器支持随机訪问,因此为了提高效率,它内部使用动态数组的方式实现的。在通过 reserve() 来申请特定大小的时候总是按指数边界来增大其内部缓冲区。当进行insert或push_back等添加元素的操作时,假设此时动态数组的内存不够用,就要动态的又一次分配当前大小的1.5~2倍的新内存区,再把原数组的内容复制过去。所以,在普通情况下,其訪问速度同一般数组,仅仅有在又一次分配发生时,其性能才会下降。正如上面的代码告诉你的那样。而进行pop_back操作时,capacity并不会由于vector容器里的元素降低而有所下降,还会维持操作之前的大小。对于vector容器来说,假设有大量的数据须要进行push_back,应当使用reserve()函数提前设定其容量大小,否则会出现很多次容量扩充操作,导致效率低下。

reserve成员函数同意你最小化必须进行的又一次分配的次数,因而能够避免真分配的开销和迭代器/指针/引用失效。但在我解释reserve为什么能够那么做之前,让我简要介绍有时候令人困惑的四个相关成员函数。在标准容器中,仅仅有vector和string提供了全部这些函数。

(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 v;
for (int i = 1; i <= 1000; ++i) v.push_back(i);
在大多数STL实现中,这段代码在循环过程中将会导致2到10次又一次分配。(10这个数没什么奇怪的。记住vector在又一次分配发生时一般把容量翻倍,而1000约等于210。)

把代码改为使用reserve,我们得到这个:

vector v;
v.reserve(1000);
for (int i = 1; i <= 1000; ++i) v.push_back(i);
这在循环中不会发生又一次分配。

在大小和容量之间的关系让我们能够预言什么时候插入将引起vector或string运行又一次分配,并且,能够预言什么时候插入会使指向容器中的迭代器、指针和引用失效。比如,给出这段代码,

string s;

if (s.size() < s.capacity()) {
s.push_back(‘x’);
}
push_back的调用不会使指向这个string中的迭代器、指针或引用失效,由于string的容量保证大于它的大小。假设不是运行push_back,代码在string的任何位置进行一个insert,我们仍然能够保证在插入期间没有发生又一次分配,可是,与伴随string插入时迭代器失效的一般规则一致,全部从插入位置到string结尾的迭代器/指针/引用将失效。

回到本条款的主旨,通常有两情况使用reserve来避免不必要的又一次分配。第一个可用的情况是当你确切或者大约知道有多少元素将最后出如今容器中。那样的话,就像上面的vector代码,你仅仅是提前reserve适当数量的空间。另外一种情况是保留你可能须要的最大的空间,然后,一旦你加入完所有数据,修整掉不论什么多余的容量。

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& v )
{
vectorvtTemp;
vtTemp.swap( v );
}

vector v ;
nums.push_back(1);
nums.push_back(3);
nums.push_back(2);
nums.push_back(4);
vector().swap(v);

/* 或者v.swap(vector()); */

/或者{ std::vector tmp = v; v.swap(tmp); }; //加大括号{ }是让tmp退出{ }时自己主动析构/

五、Vector 内存管理成员函数的行为測试
C++ STL的vector使用很广泛,可是对其内存的管理模型一直有多种推測,以下用实例代码測试来了解其内存管理方式,測试代码例如以下:

#include
#include
using namespace std;

int main()
{
vector iVec;
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //1个元素, 容器容量为1

iVec.push_back(1);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //2个元素, 容器容量为2

iVec.push_back(2);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //3个元素, 容器容量为4

iVec.push_back(3);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //4个元素, 容器容量为4

iVec.push_back(4);
iVec.push_back(5);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //5个元素, 容器容量为8

iVec.push_back(6);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //6个元素, 容器容量为8

iVec.push_back(7);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //7个元素, 容器容量为8

iVec.push_back(8);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //8个元素, 容器容量为8

iVec.push_back(9);
cout << "容器 大小为: " << iVec.size() << endl;
cout << "容器 容量为: " << iVec.capacity() << endl; //9个元素, 容器容量为16
/* vs2005/8 容量增长不是翻倍的,如
9个元素 容量9
10个元素 容量13 */

/* 測试effective stl中的特殊的交换 swap() */
cout << "当前vector 的大小为: " << iVec.size() << endl;
cout << "当前vector 的容量为: " << iVec.capacity() << endl;
vector(iVec).swap(iVec);

cout << "暂时的vector对象 的大小为: " << (vector(iVec)).size() << endl;
cout << "暂时的vector对象 的容量为: " << (vector(iVec)).capacity() << endl;
cout << "交换后,当前vector 的大小为: " << iVec.size() << endl;
cout << "交换后,当前vector 的容量为: " << iVec.capacity() << endl;

return 0;
}

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

#include <string.h>#include <vector>
#include <iostream>
using namespace std;
int main()
{vector<int>obj;//创建一个向量存储容器 intfor(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

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

C++——容器小整理相关推荐

  1. 一些简答题技巧小整理

    这份小整理是个人的一些小感悟,可能有些片面的东西,请大家多多指正! 简单的逻辑推论题 题 型 1 : A 1 如 何 影 响 B 题型1:A1如何影响B 题型1:A1如何影响B 一堆 A1 A2 An ...

  2. Kubernetes家族容器小管家Pod在线答疑?

    Kubernetes家族容器小管家Pod在线答疑❓ 不知道学习k8s的小伙伴们有没有跟我一样的疑问? k8s为什么不是直接运行容器,而是让Pod介入? Pod又是什么?为什么在应用容器化如此普遍的情况 ...

  3. css居父容器下,整理:子容器垂直居中于父容器的方案

    本文在evernote里有备份.如果evernote的阅读区域嫌窄了,那么可以把这个链接拖入书签并点击javascript:jQuery("#container").width(9 ...

  4. Android开发-基本概念小整理(二)为了面试的小伙伴们所准备~~

    转载请注明出处: http://blog.csdn.net/iwanghang/article/details/53505926 我正在参加CSDN 2016博客之星评选,希望得到您的宝贵一票~ ht ...

  5. 【图像分割】FCN学习笔记小整理

    目录 理论 代码 理论     CNN的平移不变性是什么? https://blog.csdn.net/ytusdc/article/details/107666902 基础的卷积.池化这些操作是满足 ...

  6. NLP数据分词小整理

    知识提取 知识提取是要解决结构化数据生成的问题.但是广义上讲,知识提取是数据质量提升中的一环,各种提升数据质量的方法,都可以视为某种知识提取.学术上一般是用自然语言处理的方法,但在实践中通常是利用规则 ...

  7. 设计模式的一些小整理

    ?设计模式 设计模式概述 设计模式(Design pattern)是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结.使用设计模式是为了可重用代码.让代码更容易被他人理解.保证代码可靠 ...

  8. 开发机直连 Docker 中的 Redis 容器小教程

    在笔者日常开发中,都是把redis装在windows系统中.虽然可以通过RedisDesktopManager等客户端工具连接操作redis,但是还是觉得low了一些.因为作为程序员,我可能更想在Li ...

  9. 英特尔笔试题小整理DIY

    某 ICSC 英文笔试题 为 xdjm 铺垫试卷全 e 文 第一部分 智力题 大概 5,6 道 1.有 5*5 表格中找规律填数字, 2.在 3 个飞标得 99 分的投法,标盘有数字 3.三角形各角有 ...

最新文章

  1. __block的初步用法
  2. 使用LaunchScreen.storyboard黑屏
  3. Mycat分库分表核心技术分析
  4. sqlserver怎么将excel表的数据导入到数据库中
  5. C++中的4个类型转换关键字
  6. Wince5.0自定义工具条
  7. JavaFX中的塔防(4)
  8. Linux中usr目录
  9. 很遗憾AI还不能审查出儿童性侵录像:沙漠也被当成小黄片
  10. 14.mac apche
  11. Tomcat基础教程(三)
  12. pycharm python脚本如何调试_Pycharm调试程序技巧小结
  13. 【JavaScript 插件】实现图片倒影效果 - reflex.js
  14. 能够编辑excel的python 软件有哪些_生产管理系统有哪些
  15. 美国目前最流行的五种量化交易模型
  16. oracle怎么装测试库,测试库csdb安装ORACLE_TEXT组件
  17. IMD下载软件的使用
  18. gitee的下载安装以及简单使用
  19. [INSHack2019]Passthru
  20. linux查看网卡是down还是up,查看Linux下网卡链接状态(up仍是down)?

热门文章

  1. ASP.NET操作DataTable各种方法总结(给Datatable添加行列、DataTable选择排序等)
  2. mysql创建表时反引号的作用
  3. kendo Grid json解析的问题
  4. JNI的方式调用DLL(SO)(上)
  5. 授人以鱼不如授人以渔,UCHome全面大解析培训活动【第三集】
  6. 使Tomcat可以下载中文文件
  7. 软件设计师 --哈夫曼树的一个经典问题
  8. string赋值-单引号和双引号的区别(php)
  9. Nacos配置文件覆盖问题
  10. linux的mysql本地yum安装_linux下使用yum安装mysql