标准库的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。
将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)
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位置插入n个elem数据。无返回值。
在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元素互换。
同上操作。
|
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个数据,数据均已缺省构造产生。
创建一个含有n个elem拷贝的vector。
创建一个以[beg;end)区间的vector。
销毁所有数据,释放内存。
|
Vector的操作:
函数
|
描述
|
operator[]
|
返回容器中指定位置的一个引用。
|
创建一个vector:
创建一个Widget类型的空的vector对象:
创建一个包含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 ( int i
= 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 ( int i
= 0 ;
i < 7 ;
i++)
v.push_back(i);
try
{
int iVal1
= v[ 7 ];
int iVal2
= v.at( 7 );
}
catch ( const exception&
e)
{
cout
<< e.what();
}
|
们使用reserve()分配了10个int型的空间,但并不没有初始化。
你可以在这个代码中尝试不同条件,观察它的结果,但是无论何时使用at(),都是正确的。
删除vector中的数据:
vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了 erase(), pop_back(), clear()来删除数据。
当你删除数据的时候,你应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。
在考虑删除等操作之前让我们静下来考虑一下在STL中的一些应用。
Remove_if() 算法:
现在我们考虑操作里面的数据。如果要使用remove_if(),我们需要在头文件中包含如下代码:
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
|
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中有效地删除数据:
1
2
3
4
5
6
7
8
|
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 )
分享到:
相关推荐
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放...
vector 是 C++ 标准库中定义的一种动态数组,它可以自动管理内存并根据需要调整大小。它是一种非常有用的数据结构,用于存储和管理一组元素。 用途 vector 可以用于各种目的,包括: 存储一组相关数据,例如学生...
vector是C++标准模版库(STL,Standard Template Library)中的部分内容。之所以认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单的说:vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。...
vector是一个标准库中的容器,使用时需要包含#include <vector>头文件,也可以说vector是一个类模板而不是一种数据类型,对它的定义,需要指定类型,需要的朋友可以参考下
概述 在编码中经常会遇到一种场景,就是要在数组或列表中查找某个元素是否存在,其实对于这种线性操作,自己实现一个循环来检查是非常简单的事情,那既然这样,为啥还要专门写篇博客来分享呢...总之,C++标准库是一个非
标准库里定义了三种类型:vector(支持快速随机访问)、list(支持快速插入、删除)、deque(双端队列)容器只定义了少量操作,大多数额外的操作由算法库提供。容器内元素的类型约束;1、元素类型必须支持赋值运算;2、...
C++ 的标准库提供许多有用的函数大多结合了模板的观念,如STL以及IO Stream。 函数模板 在c++入门中,很多人会接触swap(int&, int&)这样的函数类似代码如下: void swap(int&a , int& b) { int temp = a; a = b; ...
对于c++,查了一下,可以引用一个c++标准库Boost,可以轻松解决,但要下载,设置环境变量,因而没去弄。当然还可以用正则表达式进行匹配,但似乎都大材小用。不如就用substr()函数,而且string有find_last_not_of,...
SVG.js是一个轻量级的JavaScript库,允许你轻松操作SVG和定义动画。 SVG(Scalable Vector Graphics,可缩放矢量图形)是基于XML、用于描述二维矢量图形的一种图形格式。SVG由W3C制定,是一个开放标准。
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...
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...
全书围绕c++语言的结构来组织,开始章节介绍编程的普通概念,接下来详细介绍C++hh的继承、多态、异常处理以及标准模板库(STL),同时还包含模式和uML的介绍。本书内容系统、全面,给出了大量代码示例、自测练习、编程...
计算平均值、方差和标准差 矩阵变形 转置向量或矩阵 展开一个矩阵 计算矩阵的秩 计算行列式 获取矩阵的对角线元素 计算矩阵的迹 计算特征值和特征向量 计算点积 矩阵的相加相减 矩阵的乘法 计算矩阵的...
II(C++标准库) ,第8、9章最为重要,IO库和容器对于一个程序来说是比较基础的,记得不要在C++中还依然保持C的习惯,使用cout而不是printf()、使用vector而不是内置数组、使用迭代器进行遍历。第10、11章有点基础的...
1. 目录 1. 2. 目录 .........................................................................................................................................................1 JVM ........................