`
pengc825
  • 浏览: 8608 次
文章分类
社区版块
存档分类
最新评论

标准库的 Vector 类型详解

 
阅读更多

标准库的Vector类型详解

Vector是C++的STL里面提供的一种容器,之所以说它是一种容器,是因为它能够像容器一样,存储各种类型的对象。简单来说,Vector就是一个能够存储多种对象的动态数组。能够增加和压缩数据。

为了可以使用Vector头文件里面必须包含:

1
2
3
#include<vector>
using std::vector;

Vector的成员函数:

成员函数

功能表述

c.assign(beg,end)

c.assign(n,elem)

[beg;end)区间中的数据赋值给c

nelem的拷贝赋值给c

c.at(idx)

传回索引idx所指的数据,如果idx越界,抛出out_of_range

c.back()

传回最后一个数据,不检查这个数据是否存在。

c.begin()

传回迭代器重的可一个数据。

c.capacity()

返回容器中数据个数。

c.clear()

移除容器中所有数据。

c.empty()

判断容器是否为空。

c.end()

指向迭代器中的最后一个数据地址。

c.erase(pos)

c.erase(beg,end)

删除pos位置的数据,传回下一个数据的位置。

删除[beg,end)区间的数据,传回下一个数据的位置

c.front()

传回第一个数据。

get_allocator

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

c.insert(pos,elem)

c.insert(pos,n,elem)

c.insert(pos,beg,end)

pos位置插入一个elem拷贝,传回新数据位置。

pos位置插入nelem数据。无返回值。

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)

c1c2元素互换。

同上操作。

vector<Elem>c

vector<Elem>c1(c2)

vector<Elem>c(n)

vector<Elem>c(n,elem)

vector<Elem>c(beg,end)

c.~vector<Elem>()

创建一个空的vector

复制一个vector

创建一个vector,含有n个数据,数据均已缺省构造产生

创建一个含有nelem拷贝的vector

创建一个以[beg;end)区间的vector

销毁所有数据,释放内存。


Vector的操作:

函数

描述

operator[]

返回容器中指定位置的一个引用。


创建一个vector:

创建一个Widget类型的空的vector对象:

1
vector<Widget> vWidgets;

创建一个包含500个Widget类型数据的vector:

1
vector<Widget> vWidgets(500);

创建一个包含500个Widget类型数据的vector,并且都初始化为0:

1
vector<Widget> vWidgets(500, Widget(0));

创建一个Widget的拷贝:

1
vector<Widget> vWidgetsFromAnother(vWidgets);


向vector添加一个数据:

vector添加数据的缺省方法是push_back()。push_back()函数表示将数据添加到vector的尾部,并按需要来分配内存。

1
2
for(inti =0; i <10; i++)
vWidgets.push_back(Widget(i));


获取vector中指定位置的数据:

很多时候我们不必要知道vector里面有多少数据,vector里面的数据是动态分配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。如果你想知道vector存放了多少数据,你可以使用empty()。获取vector的大小,可以使用size()。

同时,我们使用两种方法来访问vector:

1
2
vector::at()
vector::operator[]

operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外。

由于operator[]容易造成一些错误,所有我们很少用它。

1
2
3
4
5
6
7
8
9
10
11
12
13
vector<int> v;
v.reserve(10);
for(inti =0; i <7; i++)
v.push_back(i);
try
{
intiVal1 = v[7]; // not bounds checked - will not throw
intiVal2 = v.at(7);// bounds checked - will throw if out of range
}
catch(constexception& e)
{
cout << e.what();
}

们使用reserve()分配了10个int型的空间,但并不没有初始化。

你可以在这个代码中尝试不同条件,观察它的结果,但是无论何时使用at(),都是正确的。


删除vector中的数据:

vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了 erase(), pop_back(), clear()来删除数据。

当你删除数据的时候,你应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。

在考虑删除等操作之前让我们静下来考虑一下在STL中的一些应用。

Remove_if() 算法:

现在我们考虑操作里面的数据。如果要使用remove_if(),我们需要在头文件中包含如下代码:

1
#include<algorithm>

Remove_if()有三个参数:

1、iterator_First:指向第一个数据的迭代指针。

2、iterator_Last:指向最后一个数据的迭代指针。

3、predicate_Pred:一个可以对迭代操作的条件函数。

条件函数:

条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指针,或者是一个函数对象。这个函数对象需要支持所有的函数调用操作,重载operator()()操作。

remove_if()是通过unary_function继承下来的,允许传递数据作为条件。

例如,假如你想从一个vector<CString>中删除匹配的数据,如果字串中包含了一个值,从这个值开始,从这个值结束。首先你应该建立一个数据结构来包含这些数据,类似代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include<functional>
enum findmodes
{
FM_INVALID =0,
FM_IS,
FM_STARTSWITH,
FM_ENDSWITH,
FM_CONTAINS
};
typedef struct tagFindStr
{
UINT iMode;
CString szMatchStr;
} FindStr;
typedef FindStr* LPFINDSTR;

然后处理条件判断:

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
32
33
34
35
36
37
38
39
40
41
42
43
classFindMatchingString
:publicstd::unary_function<CString, bool>
{
public:
FindMatchingString(constLPFINDSTR lpFS) : m_lpFS(lpFS) {}
bool operator()(CString& szStringToCompare)const
{
bool retVal =false;
switch(m_lpFS->iMode)
{
caseFM_IS:
{
retVal = (szStringToCompare == m_lpFDD->szMatchStr);
break;
}
caseFM_STARTSWITH:
{
retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())
== m_lpFDD->szWindowTitle);
break;
}
caseFM_ENDSWITH:
{
retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength())
== m_lpFDD->szMatchStr);
break;
}
caseFM_CONTAINS:
{
retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1);
break;
}
}
returnretVal;
}
private:
LPFINDSTR m_lpFS;
};

通过这个操作你可以从vector中有效地删除数据:

1
2
3
4
5
6
7
8
// remove all strings containing the value of
// szRemove from vector<CString> vs.
FindStr fs;
fs.iMode = FM_CONTAINS;
fs.szMatchStr = szRemove;
vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end());

Remove_if()能做什么?

你可能会疑惑,对于上面那个例子在调用remove_if()的时候还要使用erase()呢?

这是因为大家并不熟悉STL中的算法。

Remove(),remove_if()等所有的移出操作都是建立在一个迭代范围上的,那么不能操作容器中的数据。

所以在使用remove_if(),实际上操作的时容器里数据的上面的。

压缩一个臃肿的vector:

很多时候大量的删除数据,或者通过使用reserve(),结果vector的空间远远大于实际需要的。所有需要压缩vector到它实际的大小。resize()能够增加vector的大小。Clear()仅仅能够改变缓存的大小,所有的这些对于vector释放内存等九非常重要了。如何来解决这些问题呢,让我们来操作一下。

我们可以通过一个vector创建另一个vector。让我们看看这将发生什么。假定我们已经有一个vectorv,它的内存大小为1000,当我们调用size()的时候,它的大小仅为7。我们浪费了大量的内存。让我们在它的基础上创建一个vector。

1
2
std::vector<CString> vNew(v);
cout << vNew.capacity();

vNew.capacity()返回的是7。这说明新创建的只是根据实际大小来分配的空间。现在我们不想释放v,因为我们要在其它地方用到它,我们可以使用swap()将v和vNew互相交换一下?

1
2
3
vNew.swap(v);
cout << vNew.capacity();
cout << v.capacity();

有趣的是:vNew.capacity()是1000,而v.capacity()是7。

现在是达到我的目的了,但是并不是很好的解决方法,我们可以像下面这么写:

1
std::vector<CString>(v).swap(v);

你可以看到我们做了什么?我们创建了一个临时变量代替那个命名的,然后使用swap(),这样我们就去掉了不必要的空间,得到实际大小的v。


版权声明:本文为博主原创文章,未经博主允许不得转载。By PengCoX ( Pengc825@foxmail.com )

分享到:
评论

相关推荐

    std vector用法详解

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

    C++Vector用法详解.pdf

    vector 是 C++ 标准库中定义的一种动态数组,它可以自动管理内存并根据需要调整大小。它是一种非常有用的数据结构,用于存储和管理一组元素。 用途 vector 可以用于各种目的,包括: 存储一组相关数据,例如学生...

    C++ Vector用法详解

    vector是C++标准模版库(STL,Standard Template Library)中的部分内容。之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说:vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。...

    详解C++编程中的vector类容器用法

    vector是一个标准库中的容器,使用时需要包含#include &lt;vector&gt;头文件,也可以说vector是一个类模板而不是一种数据类型,对它的定义,需要指定类型,需要的朋友可以参考下

    C++中检查vector是否包含给定元素的几种方式详解

    概述 在编码中经常会遇到一种场景,就是要在数组或列表中查找某个元素是否存在,其实对于这种线性操作,自己实现一个循环来检查是非常简单的事情,那既然这样,为啥还要专门写篇博客来分享呢...总之,C++标准库是一个非

    C++Primer笔记之顺序容器的使用详解

    标准库里定义了三种类型:vector(支持快速随机访问)、list(支持快速插入、删除)、deque(双端队列)容器只定义了少量操作,大多数额外的操作由算法库提供。容器内元素的类型约束;1、元素类型必须支持赋值运算;2、...

    C++ Template应用详解

    C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream。 函数模板 在c++入门中,很多人会接触swap(int&, int&)这样的函数类似代码如下: void swap(int&a , int& b) { int temp = a; a = b; ...

    C++中用substr()函数消除前后空格的解决方法详解

    对于c++,查了一下,可以引用一个c++标准库Boost,可以轻松解决,但要下载,设置环境变量,因而没去弄。当然还可以用正则表达式进行匹配,但似乎都大材小用。不如就用substr()函数,而且string有find_last_not_of,...

    Svg.js实例教程及使用手册详解(一)

    SVG.js是一个轻量级的JavaScript库,允许你轻松操作SVG和定义动画。 SVG(Scalable Vector Graphics,可缩放矢量图形)是基于XML、用于描述二维矢量图形的一种图形格式。SVG由W3C制定,是一个开放标准。

    (超赞)JAVA精华之--深入JAVA API

    2.8 JSTL(JSP标准标签库)介绍 3 JAVA扩展 3.1 Log4j基本使用方法 3.2 Dom4j 使用简介 3.3 Java 语言的 XML 验证 API 3.4 hibernate的hello word 3.5 JavaMail(JAVA邮件服务)API详解 3.6 jxl.jar 包简介 3.7 Java...

    JAVA SE学习精华集锦

    2.8 JSTL(JSP标准标签库)介绍 115 3 JAVA扩展 119 3.1 Log4j基本使用方法 119 3.2 Dom4j 使用简介 120 3.3 Java 语言的 XML 验证 API 138 3.4 hibernate的hello word 143 3.5 JavaMail(JAVA邮件服务)API详解 145...

    Absolute C++中文版(原书第2版)-完美的C++教程,文档中还包含英文版

    全书围绕c++语言的结构来组织,开始章节介绍编程的普通概念,接下来详细介绍C++hh的继承、多态、异常处理以及标准模板库(STL),同时还包含模式和uML的介绍。本书内容系统、全面,给出了大量代码示例、自测练习、编程...

    Numpy中对向量、矩阵的使用详解

    计算平均值、方差和标准差 矩阵变形 转置向量或矩阵 展开一个矩阵 计算矩阵的秩 计算行列式 获取矩阵的对角线元素 计算矩阵的迹 计算特征值和特征向量 计算点积 矩阵的相加相减 矩阵的乘法 计算矩阵的...

    java坑爹的笔试题-cpp-primer-5th:C++Primer第五版学习资料

    II(C++标准库) ,第8、9章最为重要,IO库和容器对于一个程序来说是比较基础的,记得不要在C++中还依然保持C的习惯,使用cout而不是printf()、使用vector而不是内置数组、使用迭代器进行遍历。第10、11章有点基础的...

    JAVA核心知识点整理(有效)

    1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................

Global site tag (gtag.js) - Google Analytics