概述

C++内置的数组支持容器的机制,但是它不支持容器抽象的语义。要解决此问题我们自己实现这样的类。在标准C++中,用容器向量(vector)实现。

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

vector是一个类模板,不是一种数据类型。可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此vector <int >等都是数据类型。

vector对象初始化

vector 类定义了好几种构 造函数,用来定义和初始化 vector 对象。

初始化 vector 对象的方式

vector <T >  v1 ;

vector 保存类型为 T 的对象。默认构造函数 v1 为空。

vector < T > v2 ( v1 );

v2 是 v1 的一个副本。

vector < T > v3 ( n , i );

v3 包含 n 个值为 i 的元素。

vector < T > v4 ( n );

v4 含有值初始化的元素的 n 个副本。

创建确定个数的元素

若要创建非空的 vector 对象,必须给出初始化元素的值。当把一个 vector 对象复制到另一个 vector 对象时,新复制的 vector 中每一个元素都初始化为原 vector 中相应元素的副本。但这两个 vector 对象必须保存同一种元素类型:

vector<int> ivec1;                // ivec1 holds objects of type int

vector<int> ivec2(ivec1);       // ok: copy elements of ivec1 into ivec2

vector<string> svec(ivec1);    // error: svec holds strings, not ints

可以用元素个数和元素值对 vector 对象进行初始化。构造函数用元素个数来决定 vector 对象保存元素的个数,元素值指定每个元素的初始值:

vector<int> ivec4(10, -1);           // 10 elements, each initialized to -1

vector<string> svec(10, "hi!");   // 10 strings, each initialized to "hi!"

值初始化

如果没有给出元素的初始化式,那么标准库将提供一个 值初始化的 ( value initialized )元素初始化式。这个由库生成的初始值用于初始化容器中的每个元素。而元素初始化式的值取决于存储在 vector 中元素的数据类型。

如果 vector 保存内置类型(如 int 类型) 的元素,那么标准库将用 0 值创建元素初始 化值:

vector<string> fvec(10); // 10 elements, each initialized to 0

如果向量保存类类型(如 string )的元素,标准库将用该类型的默认构造函数 创建 元素初始值:

vector<string> svec(10); // 10 elements, each an empty string

vector对象操作

vector 基本操作

v. empty()

如果 v 为空,则返回 true, 否则返回 false 。

v . size ()

返回 v 中元素的个数。

v . push _ back ( t )

在 v 的末尾增加一个值为 t 的元素。

v [ n ]

返回 v 中位置为 n 的元素。

v1 = v2

把 v1 的元素替换为 v2 中元素的副本。

v1 == v2

如果 v1 与 v2 相等,则返回 true 。

!=, <, <=, >, >=

保持这些操作符惯有的含义。

vector 对象的 size

empty 和 size 操作类似于 string 类型的相关操作。成员函数 size 返回相应 vector 类定义的size_type 的值。

使用 size_type 类型时,必须指出该类型是在哪里定义的。 vector 类型总是 包括 vector 的元素类型:

vector<int>::size_type        // ok

vector::size_type          // error

向 vector 添加元素

push_back() 操作接受一个元素值,并将它作为一个新的元素添加到 vector 对象的后面,也就是“ 插入 ( push)” 到 vector 对象的 “ 后面 ( back ) ” :

// read words from the standard input and store them as elements in a vector
string word;
vector<string> text; // empty vector
while (cin >> word) {
text.push_back(word); // append word to text
}

该循环从标准输入读取一系列 string 对象,逐一追加到 vector 对象的后面。首先定义一个空的 vector 对象 text 。每循环一次就添加一个新元素到 vector 对象,并将从 输入 读取的 word 值赋予该元素。当循环结束时, text 就包含了所有读入的元素。

vector 的下标操作(更推荐用迭代器)

vector 中的对象是没有命名的,可以按 vector 中对象的位置来访问它们。通常使用下标操作符来获取元素。 vector的下标操作类似于 string 类型的下标操作 ( 3 .2 .3 节 ) 。

vector 的下标操作符接受一个值,并返回 vector 中该对应位置的元素。 vector 元素的位置从 0 开始。下例使用 for循环把 vector 中的每个元素值都重置为 0 :

// reset the elements in the vector to zero
for (vector<int>::size_type ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 0;

和 string 类型的下标操作符一样, vector 下标操作的结果为左值,因此可以像循环体中所做的那样实现写入。另外,和 string 对象的下标操作类似,这里用 size_type 类型作为 vector 下标的类型。

在上例中,即使 ivec 为空, for 循环也会正确执行。 ivec 为空则调用 size 返回 0 ,并且 for 中的测试比较 ix 和 0 。第一次循环时,由于 ix 本身就是 0 ,则条件测试失败, for 循环体一次也不执行。

仅能对确知已存在的元素进行下标操作          

初学 C ++ 的程序员可能会认为 vector 的下标操作可以添加元素,其实不然:

vector<int> ivec;   // empty vector
for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec[ix] = ix; // disaster: ivec has no elements

上述程序试图在 ivec 中插入 10 个新元素,元素值依次为 0 到 9 的整数。但是,这里 ivec 是空的 vector 对象,而且下标只能用于获取已存在的元素。

这个循环的正确写法应该是:

for (vector<int>::size_type ix = 0; ix != 10; ++ix)
ivec.push_back(ix); // ok: adds new element with value ix 

 必须是已存在的元素才能用下标操作符进行索引。通过下标操作进行赋值时,不会添加任何元素。

 
   

对于下标操作符 ( [] 操作符 ) 的使用有一点非常重要,就是仅能提取确实已存在的元素,例如:

vector<int> ivec;      // empty vector
cout << ivec[0]; // Error: ivec has no elements! vector<int> ivec2(10); // vector with 10 elements
cout << ivec[10]; // Error: ivec has elements 0...9

试图获取不存在的元素必然产生运行时错误。和大多数同类错误一样,不能确保执行过程可以捕捉到这类错误,运行程序的结果是不确定的。由于取不存在的元素的结果是未定义的,因而不同的实现会导致不同的结果,但程序运行时几乎肯定会以某种有趣的方式失败。

本警告适用于任何使用下标操作的时候,如 string 类型的下标操作,以及将要简要介绍的内置数组的下标操作。

不幸的是,试图对不存在的元素进行下标操作是程序设计过程中经常会犯的严重错误。所谓的“缓冲区溢出”错误就是对不存在的元素进行下标操作的结果。这样的缺陷往往导致 PC 机和其他应用中最常见的安全问题。

其他以及迭代器

① v.resize(2*v.size)或v.resize(2*v.size, 99) 将v的容量翻倍(并把新元素的值初始化为99)

②使用迭代器访问元素.

vector<int>::iterator it;
for(it=vec.begin();it!=vec.end();it++)
cout<<*it<<endl;

 c.insert(pos,elem) // 在pos位置插入一个elem拷贝,传回新数据位置。
 c.insert(pos,n,elem) // 在pos位置插入n个elem数据。无返回值。
 c.insert(pos,beg,end) // 在pos位置插入在[beg,end)区间的数据。无返回值。

vec.insert(vec.begin()+i,a);    在第i+1个元素前面插入a;

c.erase(pos)          删除pos位置的数据,传回下一个数据的位置。

c.erase(beg,end)    删除[beg,end)区间的数据,传回下一个数据的位置。

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.begin()传回迭代器中的第一个数据

c.clear()移除容器中所有数据。

c.empty()判断容器是否为空。

c.end()指向迭代器中末端元素的下一个,指向一个不存在元素。

其他更多参见百科:
http://baike.baidu.com/link?url=L6vhhZKTvp6C62nPFPbYKnxbqXnRUTwt-2dV7e07ACU0CnFJ6kbyDbwQ-iPGqoY_

More:vector结构体

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

#include<stdio.h>
#include<algorithm>
#include<vector>
#include<iostream>
using namespace std; typedef struct rect
{
int id;
int length;
int width;   //对于向量元素是结构体的,可在结构体内部定义比较函数,下面按照id,length,width升序排序。
  bool operator< (const rect &a) const
{
if(id!=a.id)
return id<a.id;
else
{
if(length!=a.length)
return length<a.length;
else
return width<a.width;
}
}
}Rect; int main()
{
vector<Rect> vec;
Rect rect;
rect.id=1;
rect.length=2;
rect.width=3;
vec.push_back(rect);
vector<Rect>::iterator it=vec.begin();
cout<<(*it).id<<' '<<(*it).length<<' '<<(*it).width<<endl; return 0; }

算法:

#include<algorithm>中的泛函算法

搜索算法:find() 、search() 、count() 、find_if() 、search_if() 、count_if() 


分类排序:sort() 、merge() 


删除算法:unique() 、remove() 


生成和变异:generate() 、fill() 、transformation() 、copy() 


关系算法:equal() 、min() 、max() 


sort(v1.begin(),vi.begin()+v1.size/2); 对v1的前半段元素排序


list<char>::iterator pMiddle =find(cList.begin(),cList.end(),'A');找到则返回被查内容第一次出现处指针,否则返回end()。


vector< typeName >::size_type x ; vector< typeName >类型的计数,可用于循环如同for(int i)

使用reverse将元素翻转

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

一般后一个都不包含.)

使用sort排序

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

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

定义排序比较函数:

bool Comp(const int &a,const int &b)
{
return a>b;
}

调用时:sort(vec.begin(),vec.end(),Comp),这样就降序排序。

/*
vector 综合练习
Written by C_SuooL_Hu
2013 10 29
*/ #include <vector>
#include <string>
#include <iostream>
#include <algorithm> using namespace std ; int main()
{
// 四种初始化方式
vector<int> ivec_1;
vector<int> ivec_2(ivec_1);
vector<int> ivec_3(10, 0) ;
vector<int> ivec(10);
// 定义迭代器变量
vector<int>::iterator iter;
// 定义下标变量
vector<int>::size_type ix ; system("echo off");
system("color 3") ;
// reset all the elements in ivec to 0
// 使用下标操作,重置为1
for (ix = 0; ix != ivec.size(); ++ix)
ivec[ix] = 1;
// print what we've got so far: should print 10 0's
cout << "使用下标赋值为1的vector<int>类型(同样用下标遍历输出):"<< endl;
for (ix = 0; ix != ivec.size(); ++ix)
cout << ivec[ix] << " ";
cout << endl;
// 使用迭代器的操作赋值,重置为0
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
*iter = 0;
// 遍历输出,使用迭代器
cout<<"使用迭代器赋值为0的vector<int>类型(同样用迭代器遍历输出):" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout<< endl ; iter = ivec.begin();
while (iter != ivec.end())
{
*iter =2 ;
++iter;
}
// 遍历输出,使用迭代器
cout<<"使用while循环的迭代器赋值为2的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout<< endl << endl ; // 使用vector的成员函数操作vector<int>类型数据
// 添加元素
cout << "使用vector的成员函数操作vector<int>类型数据" << endl;
cout << "添加元素" << endl ;
cout << "使用迭代器,添加九个递增元素" << endl ;
for (ix = 0; ix != 10; ++ ix)
ivec.push_back(ix);
cout << "此时ivec共有" << ivec.size() << "个元素"<< endl;
// 遍历输出,使用迭代器
cout<<"使用下标增加元素为递增的的数列的vector<int>类型(同样用迭代器遍历输出):" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout<< endl << endl; // 插入元素
cout << "插入元素:在第二个位置插入一个43" << endl ;
ivec.insert(ivec.begin() + 1, 43); // 在2位置插入一个43拷贝,传回新数据位置。
// 遍历输出,使用迭代器
cout<<"使用迭代器遍历输出:" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout << "\n此时ivec共有" << ivec.size() << "个元素" ;
cout<< endl << endl ; cout << "插入元素:在第一个位置插入三个13" << endl ;
ivec.insert(ivec.begin(), 3 , 13); // 在1位置插入3个13数据。无返回值。
// 遍历输出,使用迭代器
cout<<"使用迭代器遍历输出:" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout << "\n此时ivec共有" << ivec.size() << "个元素";
cout<< endl << endl ; cout << "插入元素:在第7个位置插入ivec的[1, 6) 之间的数据:" << endl ;
ivec.insert(ivec.begin()+6, ivec.begin(), ivec.begin()+5); // 在7位置插入在[10,19)区间的数据。无返回
// 遍历输出,使用迭代器
cout<<"使用迭代器遍历输出:" << endl;
for (iter = ivec.begin(); iter !=ivec.end(); ++iter )
cout<< *iter << ' ' ;
cout << "\n此时ivec共有" << ivec.size() << "个元素";
cout<< endl << endl ; cout << "使用assign赋值ivec_1(将ivec的第[10,19)个元素赋值给他):" <<endl ;
ivec_1.assign(ivec.begin()+9, ivec.begin()+18);
cout<<"使用迭代器遍历输出:" << endl;
for (iter = ivec_1.begin(); iter !=ivec_1.end(); ++iter )
cout<< *iter << ' ' ;
cout << "\n此时ivec_1共有" << ivec_1.size() << "个元素";
cout << endl; cout << "使用assign赋值ivec_2:" <<endl ;
ivec_2.assign(10,8) ;
cout<<"使用迭代器遍历输出:" << endl;
for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
cout<< *iter << ' ' ;
cout << "\n此时ivec_2共有" << ivec_2.size() << "个元素";
cout << endl;
// 元素排序
/*
由于vc 6.0对模板库支持不够好,这里的排序函数无法通过编译,但是使用vs2010编译通过。
cout << "对ivec排序:" << endl;
bool Comp(const int &a,const int &b)
{
return a>b;
}
sort (ivec.begin(), ivec.end,Comp);
cout<<"从大到小排序后,使用迭代器遍历输出:" << endl;
for (iter = ivec_2.begin(); iter !=ivec_2.end(); ++iter )
cout<< *iter << ' ' ;
*/ cout << "是否为空(0代表不是,1代表是):" << ivec.empty() << endl;
ivec.clear() ;
cout << "清空元素" << endl;
cout << "是否为空:" << ivec.empty() << endl;
return 0;
}

运行结果:







C++ vector类型要点总结的更多相关文章

  1. C++ vector类型要点总结(以及各种algorithm算法函数)

    概述 C++内置的数组支持容器的机制,但是它不支持容器抽象的语义.要解决此问题我们自己实现这样的类.在标准C++中,用容器向量(vector)实现. 容器向量也是一个类模板.vector是C++标准模 ...

  2. Spark DataFrame vector 类型存储到Hive表

    1. 软件版本 软件 版本 Spark 1.6.0 Hive 1.2.1 2. 场景描述 在使用Spark时,有时需要存储DataFrame数据到Hive表中,一般的存储方式如下: // 注册临时表 ...

  3. vector类型介绍

    一.vector类型简介 标准库:集合或动态数组,我们可以放若干对象放在里面. vector他能把其他对象装进来,也被称为容器 #include <iostream> #include & ...

  4. 【原创】【长期更新】【未完待续】自制vector类型

    继<自制string类型>以来的第二篇自制类型的文章.马上要开学了,时间也不多了,争取在今年写完吧. 目录 一,vector类型简单介绍 1.简介 1.1.STL 1.2.vector 2 ...

  5. C++标准库vector类型详解

    Vector简介 vector是定义在C++标准模板库,它是一个多功能.能够操作多种数据结构和算法的模板类(关于模板类我们后面会介绍,如何创建自己的模板类).vector是一个容器,能够像容器一样存放 ...

  6. C++标准库vector类型的使用和操作总结

    vector是一种类型对象的集合,它是一种顺序容器,容器中的所有对象必须都是同一种类型.想了解顺序容器的更多内容:C++顺序容器知识总结.vector的对象是可以动态生长的,这说明它在初始化时可以不用 ...

  7. C++ STL vector类型

    vector容器是一个模板类,可以存放任何类型的对象(但必须是同一类对象).vector对象可以在运行时高效地添加元素,并且vector中元素是连续存储的.注:vector容器内存放的所有对象都是经过 ...

  8. Rust中的Vector类型

    常用类型操作, 如python中的list,turple,dictory等, 更方常编程常用数据的处理. fn main() { let v = vec![, , , , ]; let third: ...

  9. C++之vector模板类

    vector 称为容器模板类,是同一种类型的对象的集合,每个对象都有一个对应的整数索引值.vector 不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型.vector 类型的每一种都指定 ...

随机推荐

  1. py脚本打包exe可执行文件

    python3以上版本打包exe需要扩展软件:cx_freeze 下载地址:http://cx-freeze.sourceforge.net/ 1)安装后在\Python32\Scripts\cxfr ...

  2. C#高级编程9-第9章 字符串和正则表达式

    字符串和正则表达式 String类 String类对象是不可改变的,对于String对象的重新赋值在本质上是重新创建了一个String对象并将新值赋予该对象,其方法ToString对性能的提高并非很显 ...

  3. Mac安装homebrew安装到指定目录

    第一种直接安装在/usr/local目录下 mac 打开终端输入 ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebr ...

  4. react父子组件数据传递

    子传父 1.首先父组件设定一个自定义函数 getChildDatas = (values) => { //...业务代码 } 2.将该函数暴露在子组件的引用上 <Child getChil ...

  5. 自动化运维工具 ~puppet~

    一.模板的应用 到目前为止,资源申报.定义类.声明类等所有功能都只能一个manifest文件中实现,但这却非有效的基于puppet管理IT资源架构的方式.实践 中,一般需要把manifest文件分解成 ...

  6. WPF中删除打开过的图片

    在WPF中,当我们删除打开过的图片时,往往会遇到"...无法删除,文件正在被另一个进程使用"的异常.即使当前文件是打开后关闭过的也不行. 这个问题的原因很简单,是因为WPF的缓存策 ...

  7. 绝对定位的div的居中方法,下面的写法兼容IE系列浏览器和火狐浏览器。

    详细解说,直接看样式:#dingwei{padding:10px;background-color:#003300;color:#FFFFFF; width:600px;height:300px; d ...

  8. 安装wp8sdk 当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内。

    安装wp8sdk 当前系统时钟或签名文件中的时间戳验证时要求的证书不在有效期内. [1404:0090][2015-06-12T08:00:53]: Error 0x800b0101: Failed ...

  9. “System.InvalidOperationException”类型的未经处理的异常在 ESRI.ArcGIS.AxControls.dll 中发生

    问题描述: 新手们进行ArcGIS ArcObject开发时经常会遇到各种十分古怪的问题,比如下面的这个问题: “System.InvalidOperationException”类型的未经处理的异常 ...

  10. Selenium2+python自动化46-js解决click失效问题

    前言 有时候元素明明已经找到了,运行也没报错,点击后页面没任何反应.这种问题遇到了,是比较头疼的,因为没任何报错,只是click事件失效了. 本篇用2种方法解决这种诡异的点击事件失效问题 一.遇到的问 ...