C++中vector使用详细说明 (转)

转自:http://blog.chinaunix.net/uid-26000296-id-3785610.html

http://www.cnblogs.com/mr-wid/archive/2013/01/22/2871105.html

一、向量的介绍
    向量 vector 是一种对象实体, 能够容纳许多其他类型相同的元素, 因此又被称为容器。 与string相同, vector 同属于STL(Standard Template Library, 标准模板库)中的一种自定义的数据类型, 可以广义上认为是数组的增强版。
    
    在使用它时, 需要包含头文件 vector, #include<vector>
    
    vector 容器与数组相比其优点在于它能够根据需要随时自动调整自身的大小以便容下所要放入的元素。此外, vector 也提供了许多的方法来对自身进行操作。
    
    

 


二、向量的声明及初始化
    vector 型变量的声明以及初始化的形式也有许多, 常用的有以下几种形式:

复制代码
        vector<int> a ;                                //声明一个int型向量avector<int> a(10) ;                            //声明一个初始大小为10的向量vector<int> a(10, 1) ;                         //声明一个初始大小为10且初始值都为1的向量vector<int> b(a) ;                             //声明并用向量a初始化向量bvector<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的初值

 


        
        
三、元素的输入及访问
    元素的输入和访问可以像操作普通的数组那样, 用cin>>进行输入, cout<<a[n]这样进行输出:
    示例:

复制代码
 1     #include<iostream>2     #include<vector>3 4     using namespace std ;5 6     int main()7     {8         vector<int> a(10, 0) ;      //大小为10初值为0的向量a9 
10         //对其中部分元素进行输入
11         cin >>a[2] ;
12         cin >>a[5] ;
13         cin >>a[6] ;
14 
15         //全部输出
16         int i ;
17         for(i=0; i<a.size(); i++)
18             cout<<a[i]<<" " ;
19 
20         return 0 ;
21     }
复制代码

    
    在元素的输出上, 还可以使用遍历器(又称迭代器)进行输出控制。在 vector<int> b(a.begin(), a.begin()+3) ; 这种声明形式中, (a.begin()、a.begin()+3) 表示向量起始元素位置到起始元素+3之间的元素位置。(a.begin(), a.end())则表示起始元素和最后一个元素之外的元素位置。
    向量元素的位置便成为遍历器, 同时, 向量元素的位置也是一种数据类型, 在向量中遍历器的类型为: vector<int>::iterator。 遍历器不但表示元素位置, 还可以再容器中前后移动。
    
    在上例中讲元素全部输出部分的代码就可以改写为:

    //全部输出vector<int>::iterator t ;for(t=a.begin(); t!=a.end(); t++)cout<<*t<<" " ;

        
    *t 为指针的间接访问形式, 意思是访问t所指向的元素值。
    
    

 


四、向量的基本操作

复制代码
      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>. 交换 - swapb.swap(a) ; //a向量与b向量进行交换
复制代码

 


        
        
五、二维向量
    与数组相同, 向量也可以增加维数, 例如声明一个m*n大小的二维向量方式可以像如下形式:

        vector< vector<int> > b(10, vector<int>(5));        //创建一个10*5的int型二维向量

 
    在这里, 实际上创建的是一个向量中元素为向量的向量。同样可以根据一维向量的相关特性对二维向量进行操作。
    
    :

复制代码
 1     #include<iostream>2     #include<vector>3 4     using namespace std ;5 6     int main()7     {8         vector< vector<int> > b(10, vector<int>(5, 0)) ;9 
10         //对部分数据进行输入
11         cin>>b[1][1] ;
12         cin>>b[2][2] ;
13         cin>>b[3][3];
14 
15         //全部输出
16         int m, n ;
17         for(m=0; m<b.size(); m++)           //b.size()获取行向量的大小
18         {
19             for(n=0; n<b[m].size(); n++)    //获取向量中具体每个向量的大小
20                 cout<<b[m][n]<<" " ;
21             cout<<"\n" ;
22         }
23 
24         return 0;
25     }
复制代码

    
    同样, 按照这样的思路我们还可以创建更多维的向量, 不过维数太多会让向量变得难以灵活控制, 三维以上的向量还需酌情使用。

___________________________________________________________________________________________________________________________________________________________________

1. 在C++中的详细说明
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。
vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,
简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。


2. 使用vector,
必须在你的头文件中包含下面的代码:
  #include 


vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:
  using std::vector;
  vector vInts;
  
或者连在一起,使用全名:  
    std::vector vInts;
  
建议使用全局的命名域方式:
    using namespace std;


3. 初始化   
vector                 // 创建一个空的vector。
vector c1(c2)          // 复制一个vector
vector c(n)            // 创建一个vector,含有n个数据,数据均已缺省构造产生
vector c(n, elem)      // 创建一个含有n个elem拷贝的vector
vector c(beg,end)      // 创建一个含有n个elem拷贝的vector


4. 析构函数
c.~vector ()           // 销毁所有数据,释放内存


5. 成员函数
c.assign(beg,end)c.assign(n,elem)
  将[beg; end)区间中的数据赋值给c。将n个elem的拷贝赋值给c。
c.at(idx)
  传回索引idx所指的数据,如果idx越界,抛出out_of_range。


c.back()      // 传回最后一个数据,不检查这个数据是否存在。
c.begin()     // 传回迭代器中的第一个数据地址。
c.capacity()  // 返回容器中数据个数。
c.clear()     // 移除容器中所有数据。
c.empty()     // 判断容器是否为空。
c.end()       // 指向迭代器中末端元素的下一个,指向一个不存在元素。
c.erase(pos)  // 删除pos位置的数据,传回下一个数据的位置。
c.erase(beg,end)  //删除[beg,end)区间的数据,传回下一个数据的位置。
c.front()     // 传回第一个数据。


get_allocator // 使用构造函数返回一个拷贝。


c.insert(pos,elem)    // 在pos位置插入一个elem拷贝,传回新数据位置。
c.insert(pos,n,elem)  // 在pos位置插入n个elem数据。无返回值。
c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。
  
c.max_size()       // 返回容器中最大数据的数量。
c.pop_back()       // 删除最后一个数据。
c.push_back(elem)  // 在尾部加入一个数据。
c.rbegin()         // 传回一个逆向队列的第一个数据。
c.rend()           // 传回一个逆向队列的最后一个数据的下一个位置。
c.resize(num)      // 重新指定队列的长度。
c.reserve()        // 保留适当的容量。
c.size()           // 返回容器中实际数据的个数。
c1.swap(c2)
swap(c1,c2)        // 将c1和c2元素互换。同上操作。

operator[]         // 返回容器中指定位置的一个引用。

6. 用法示例:
6.1. 创建一个vector
vector容器提供了多种创建方法,下面介绍几种常用的。
创建一个Widget类型的空的vector对象:
  vector vWidgets;
  
创建一个包含500个Widget类型数据的vector:
  vector vWidgets(500);
  
创建一个包含500个Widget类型数据的vector,并且都初始化为0:
  vector vWidgets(500, Widget(0));
  
创建一个Widget的拷贝:
  vector vWidgetsFromAnother(vWidgets);
  
向vector添加一个数据
  vector添加数据的缺省方法是push_back()。
    push_back()函数表示将数据添加到vector的尾部,并按需要来分配内存。


例如:向vector中添加10个数据,需要如下编写代码:
  for(int i= 0;i<10; i++) {
    vWidgets.push_back(Widget(i));
  }


6.2 获取vector中指定位置的数据
  vector里面的数据是动态分配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。
    如果想知道vector存放了多少数据,可以使用empty()。
    获取vector的大小,可以使用size()。


例如,如果想获取一个vector v的大小,但不知道它是否为空,或者已经包含了数据,如果为空想设置为-1,
你可以使用下面的代码实现:
  int nSize = v.empty() ? -1 : static_cast(v.size());
  
6.3 访问vector中的数据
使用两种方法来访问vector。
1、 vector::at()
2、 vector::operator[]
  operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。
    但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外。
    由于operator[]容易造成一些错误,所有我们很少用它,下面进行验证一下:
  
分析下面的代码:
  vector v;
  v.reserve(10);
  
    for(int i=0; i<7; i++) {
    v.push_back(i);
  }
  
    try {int iVal1 = v[7];
    // not bounds checked - will not throw
    int iVal2 = v.at(7);
    // bounds checked - will throw if out of range
  } 
    
    catch(const exception& e) {
    cout << e.what();
  }
  
6.3 删除vector中的数据
vector能够非常容易地添加数据,也能很方便地取出数据,
同样vector提供了erase(),pop_back(),clear()来删除数据,
当删除数据时,应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。

Remove_if()算法 如果要使用remove_if(),需要在头文件中包含如下代码::
  #include 

Remove_if()有三个参数:
  1、 iterator _First:指向第一个数据的迭代指针。
  2、 iterator _Last:指向最后一个数据的迭代指针。
  3、 predicate _Pred:一个可以对迭代操作的条件函数。
  
6.4 条件函数
条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指针,或是一个函数对象。
这个函数对象需要支持所有的函数调用操作,重载operator()()操作。
remove_if()是通过unary_function继承下来的,允许传递数据作为条件。


例如,假如想从一个vector中删除匹配的数据,如果字串中包含了一个值,从这个值开始,从这个值结束。
首先应该建立一个数据结构来包含这些数据,类似代码如下:
#include 
enum findmodes {
  FM_INVALID = 0,
  FM_IS,
 FM_STARTSWITH,
 FM_ENDSWITH,
 FM_CONTAINS
};

typedef struct tagFindStr {
 UINT iMode;
 CString szMatchStr;
} FindStr;


typedef FindStr* LPFINDSTR;
  
然后处理条件判断:
class FindMatchingString : public std::unary_function<cstring, bool=""> {
public:
 FindMatchingString(const LPFINDSTR lpFS) :
 m_lpFS(lpFS) {}
 bool operator()(CString& szStringToCompare) const {
  bool retVal = false;
  
    switch (m_lpFS->iMode) {
  case FM_IS: {
    retVal = (szStringToCompare == m_lpFDD->szMatchStr);
    break;
  }
  case FM_STARTSWITH: {
    retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
      == m_lpFDD->szWindowTitle);
    break;
  }
  case FM_ENDSWITH: {
    retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
      == m_lpFDD->szMatchStr);
  break;
  }
  case FM_CONTAINS: {
    retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
    break;
  }
   }
   return retVal;
  }
private:
 LPFINDSTR m_lpFS;
};

通过这个操作你可以从vector中有效地删除数据:
    FindStr fs;
  fs.iMode = FM_CONTAINS;
  fs.szMatchStr = szRemove;
  vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());
  
Remove(),remove_if()等所有的移出操作都是建立在一个迭代范围上的,不能操作容器中的数据。
所以在使用remove_if(),实际上操作的时容器里数据的上面的。


看到remove_if()实际上是根据条件对迭代地址进行了修改,在数据的后面存在一些残余的数据,
那些需要删除的数据。剩下的数据的位置可能不是原来的数据,但他们是不知道的。
调用erase()来删除那些残余的数据。
注意上面例子中通过erase()删除remove_if()的结果和vs.enc()范围的数据。


7. 综合例子:
//---------------------------------------------------------------------------
#include 
#pragma hdrstop
#include "Unit1.h"
//---------------------------------------------------------------------------

#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
#include 
#include 
using namespace std;

struct STResult
{
    double Time;
    double Xp;
    double Yp;
    int id;
};


//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
}


vector ResultVector;


void __fastcall test()
{
    //test
    //vector ResultVector;
    STResult stritem;
    stritem.Time = .1;
    stritem.Xp = .1;
    stritem.Yp = .1;
    stritem.id = 1;


    ResultVector.push_back( stritem );


}


//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    test();
    assert(ResultVector[0].id == 1);
}
//---------------------------------------------------------------------------

转载于:https://www.cnblogs.com/aminxu/p/4686332.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/471727.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

c++ 一行输出八个数字_R语言笔记(三):数据输入与输出

本文主要介绍数据基本的输入与输出方法&#xff0c;内容包括&#xff1a;1. 数据的输入1.1 scan(), edit(), fix()1.2 调用 R 包自带数据1.3 调用本地数据2. 数据的输出1. 数据的输入1.1 scan(), edit(), fix()手动输入数据主要有以下几种方式&#xff1a;x <- c() # c() 进…

LeetCode 1985. 找出数组中的第 K 大整数(排序)

文章目录1. 题目2. 解题1. 题目 给你一个字符串数组 nums 和一个整数 k 。 nums 中的每个字符串都表示一个不含前导零的整数。 返回 nums 中表示第 k 大整数的字符串。 注意&#xff1a;重复的数字在统计时会视为不同元素考虑。 例如&#xff0c;如果 nums 是 [“1”,“2”,…

firefox应用自动全屏显示_【b】—自动化测试:基础selenium—API

一、浏览器对象# 导入webdriverfrom selenium import webdriver# 创建一个浏览器对象driver webdriver.Firefox()# 设置全屏# driver.maximize_window()# 获取当前浏览器尺寸# size driver.get_window_size()# print(size)# 设置浏览器尺寸driver.set_window_size(400, 400)s…

【linux高级程序设计】(第十三章)Linux Socket网络编程基础 2

BSD Socket网络编程API 创建socket对象 int socket (int __domain, int __type, int __protocol) &#xff1a;成功返回socket文件描述符&#xff0c;失败返回-1. 参数1&#xff1a;socket对象使用的地址簇或协议簇 常用的有PF_LOCAL(本机通信)、PF_INET(IPv4协议簇)、PF_INET6…

数据库中有痣但是有时取不到_农村这种长得像“泥鳅”的鱼,以前没人吃,现在可能有钱都吃不到...

只说真话的农民公众号原创文章&#xff0c;严禁转载在农村中有很多不能叫出名字的花草和野味&#xff0c;它们当中虽然有些长得比较奇怪&#xff0c;名字也比较奇怪&#xff0c;但是却是非常好的疗补食物。有些花草是治疗疾病的良药&#xff0c;有些野味现在也被搬上了酒桌。但…

python 使用 asyncio 包处理并发

文章目录1. 线程与协程对比2. 使用 asyncio 和 aiohttp 下载3. 避免阻塞型调用4. 使用 asyncio.as_completed5. 使用Executor对象&#xff0c;防止阻塞事件循环6. 从回调到期物和协程learn from 《流畅的python》 1. 线程与协程对比 threading import threading import iter…

LeetCode 1991. 找到数组的中间位置(前缀和)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的整数数组 nums &#xff0c;请你找到 最左边 的中间位置 middleIndex &#xff08;也就是所有可能中间位置下标最小的一个&#xff09;。 中间位置 middleIndex 是满足 nums[0] nums[1] ... nums[middleIndex-1] n…

LeetCode 1992. 找到所有的农场组(BFS)

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始&#xff0c;大小为 m x n 的二进制矩阵 land &#xff0c;其中 0 表示一单位的森林土地&#xff0c;1 表示一单位的农场土地。 为了让农场保持有序&#xff0c;农场土地之间以矩形的 农场组 的形式存在。 每一个农场组都…

VS2015开发Android,自带模拟器无法调试、加载程序,算是坑吗

VS2015出来后&#xff0c;确定变化很大&#xff0c;什么android、ios的&#xff0c;不在话下。对于我这样传统型的人&#xff0c;也第一时间试用了一下&#xff08;vs2003->vs2008->vs2012->vs2015&#xff09;。以前用eclipse开发过android小程序&#xff0c;现在想试…

amd cpu 安卓模拟器_夜神模拟器常见问题解答_v20201025

MAC版本常见问题Mac版本模拟器常见问题MAC模拟器出现“您应该将它移到废纸篓”解决办法MAC版本模拟器功能介绍MAC版本模拟器界面Mac版模拟器可能无法启动(卡99%)的原因及解决方式其他问题如何在夜神模拟器中安装自己想要的游戏/应用Sample CA 2证书没网解决办法GlobalSignature…

LeetCode 502. IPO(优先队列)

文章目录1. 题目2. 解题1. 题目 假设 力扣&#xff08;LeetCode&#xff09;即将开始 IPO 。 为了以更高的价格将股票卖给风险投资公司&#xff0c;力扣 希望在 IPO 之前开展一些项目以增加其资本。 由于资源有限&#xff0c;它只能在 IPO 之前完成最多 k 个不同的项目。 帮助…

bash 不是内部或外部命令_Win10_cmd下提示:‘xxx’不是内部或外部命令,也不是可运行的程序 或批处理文件...

一、windows下命令行查看ip: win+R,调出【运行】,输入cmd,回车打开终端,输入ipconfig,查看成功: 二、可能出现的问题: ping 不是内部或外部命令,也不是可运行的程序或批处理文件。 ipconfig 不是内部或外部命令,也不是可运行的程序或批处理文件。 解决: 1、控制面板…

python 属性描述符

文章目录1. 描述符示例&#xff1a;验证属性2. 自动获取储存属性的名称3. 继承改进4. 覆盖型与非覆盖型描述符对比4.1 覆盖型描述符4.2 没有 __get__ 方法的覆盖型描述符4.3 非覆盖型描述符4.4 在类中覆盖描述符5. 描述符用法建议learn from 《流畅的python》 1. 描述符示例&a…

计算机声音与视频教程,电脑怎么录屏幕视频带声音 电脑录屏幕视频带声音教程...

电脑怎么录屏幕视频带声音&#xff0c;相信有许多的用户在工作上或者学习上也会有这种需求&#xff0c;自己对此也还是不太的了解&#xff0c;毕竟也是没有怎么使用过&#xff0c;对此也是想要知道这电脑怎么录屏幕视频带声音&#xff0c;其实也是有几个原因&#xff0c;下面就…

tensor转换为图片_为大家介绍图片转换pdf的经验总结!你找对方法了吗?

图片转换pdf怎么做&#xff1f;不少朋友们在学习和工作中都发现了PDF这种文件格式似乎格外的吃香&#xff0c;你收到的很多培训文件和在网上搜罗的一些学习文件&#xff0c;全部都是PDF格式&#xff0c;PDF格式这么吃香&#xff1f;甚至有人让你把图片都转成PDF格式&#xff0c…

LeetCode 2021 力扣杯全国秋季编程大赛(第384名)

文章目录1. 无人机方阵2. 心算挑战3. 黑白翻转棋4. 玩具套圈5. 十字路口的交通2021.9.11&#xff0c;周六比赛之前&#xff1a;早上去交大看看&#xff0c;本科毕业10年了&#xff0c;由于限流&#xff0c;校园里没有多少回校的校友。逛了逛&#xff0c;跟太太和的她的同学一起…

java 画笔跟swing组件_Java学习教程(基础)--Java版本历史(二)

Java语言自JDK1.0版本以来经历了许多次更新&#xff0c;也在基本程序库中增加了大量的类别和包。从J2SE 1.4开始&#xff0c;Java语言的变动由 Java Community Process&#xff08;JCP&#xff09;管理&#xff0c;JCP使用Java规范请求&#xff08;Java Specification Requests…

计算机网络路由选择协议,IP路由选择协议原理和作用

IP路由选择协议原理和作用(2008-10-20 19:26:17)标签&#xff1a;杂谈IP路由选择如果目的主机与源主机直接相连或都在一个共享网络上,那就直接把包发送到目的主机,如果不是,那把ip数据报送到默认路由器,由它转发路由器使用路由表保存自己知道的网络的信息,它包括:目的IP地址,它…

LeetCode 2000. 反转单词前缀

文章目录1. 题目2. 解题1. 题目 给你一个下标从 0 开始的字符串 word 和一个字符 ch 。 找出 ch 第一次出现的下标 i &#xff0c;反转 word 中从下标 0 开始、直到下标 i 结束&#xff08;含下标 i &#xff09;的那段字符。 如果 word 中不存在字符 ch &#xff0c;则无需进…

oss图片跨域问题_图片存储解决方案-阿里云对象存储

开通对象存储OSS1. 打开阿里云官网&#xff0c;选择产品对象存储 OSS 2.开通对象存储OSS 需要支付宝扫码登录3.进入管理控制台 4.新建存储空间 5.跨域资源共享(CORS)的设置管理文件整合Springboot实现图片上传服务端签名直传并设置上传回调 : 在服务端完成签名&#xff0c;并且…