|
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说,vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。 为了可以使用vector,必须在你的头文件中包含下面的代码: #include <vector> 6 Y9 h' l9 u: q vector属于std命名域的,因此需要通过命名限定,如下完成你的代码: using std::vector; vector<int> vInts; 或者连在一起,使用全名: $ j' e, T! U. g$ N std::vector<int> vInts; 5 B/ S# h3 ~2 C# B- [9 a 建议使用全局的命名域方式:using namespace std; 9 {) v/ C4 f. l* |, @+ G 函数 ! y! }8 J4 t4 ^% S 表述 ; b1 ?5 {5 g0 L% N: J4 J c.assign(beg,end)c.assign(n,elem) $ t* |" L% n% t! t$ B; ? 将[beg; end)区间中的数据赋值给c。将n个elem的拷贝赋值给c。 c.at(idx) # j. A8 a3 F) T3 e l0 j 传回索引idx所指的数据,如果idx越界,抛出out_of_range。 c.back() ^! m; `, i' |" D 传回最后一个数据,不检查这个数据是否存在。 1 |- ~5 Y1 |4 E4 U1 w. @, [ c.begin() 传回迭代器中的第一个数据地址。 : i, r; x' ~7 @4 B c.size() . a( j( N! R- p) p 返回容器中数据个数。 ; O% K. B: i2 R, A% y! W( e% v c.clear() 移除容器中所有数据。 c.empty() 判断容器是否为空。 $ y6 o" b; z |5 T, a$ ]) O6 E c.end() ' q$ C# Q5 U! N# i 指向迭代器中末端元素的下一个,指向一个不存在元素。 - m" M- }& o4 a- @; s$ x0 G ? c.erase(pos) c.erase(beg,end) 删除pos位置的数据,传回下一个数据的位置。 , z e+ i8 w# R7 m 删除[beg,end)区间的数据,传回下一个数据的位置。 c.front() ) r9 x5 @9 p: r' m+ R5 L! `3 A 传回第一个数据。 8 p! {' x/ I5 f( W, G6 d) D get_allocator & U- V: d! X! f6 V) E) q 使用构造函数返回一个拷贝。 + D% S0 V8 X# c7 e% h. R# A3 a5 j c.insert(pos,elem) c.insert(pos,n,elem) 8 C6 g/ C+ g6 ] c.insert(pos,beg,end) % `, P5 h$ U0 |8 u' m$ q ) K+ a5 n8 \ s+ t y( T2 u* K ; _, k8 u" z% r# i" p% v 在pos位置插入一个elem拷贝,传回新数据位置。在pos位置插入n个elem数据。无返回值。在pos位置插入在[beg,end)区间的数据。无返回值。! x! [+ s/ G' U ; U: U% [! b* @1 L- V$ o' y( K+ j c.max_size() 1 j/ V; a4 ?2 [6 E 返回容器中最大数据的数量。 c.pop_back() 删除最后一个数据。 c.push_back(elem) 2 x+ t I4 |; `1 b! d; G$ @$ j 在尾部加入一个数据。 c.rbegin() 传回一个逆向队列的第一个数据。 c.rend() 传回一个逆向队列的最后一个数据的下一个位置。 c.resize(num) 重新指定队列的长度。 ( f+ `* f, L. i c.reserve() ) E V% j. C' r 保留适当的容量。 c.size() 返回容器中实际数据的个数。 " [. ?! ]" S" u- J& q4 M# I$ E5 E c1.swap(c2) # a# v" G. G/ ~- M( V: g6 V8 Z swap(c1,c2) 5 r% g! d* R8 n: ~! p8 x) k 将c1和c2元素互换。同上操作。 vector<Elem> cvector<Elem> c1(c2) vector <Elem> c(n) ector <Elem> c(n, elem) vector <Elem> c(beg,end) c.~ vector <Elem>() # A% A8 h' L! r 创建一个空的vector。复制一个vector。创建一个vector,含有n个数据,数据均已缺省构造产生。创建一个含有n个elem拷贝的vector。创建一个以[beg;end)区间的vector。销毁所有数据,释放内存。 operator[] : F G7 _& C% p6 x- L 返回容器中指定位置的一个引用。 创建一个vector * D5 W7 b1 H# ^& e vector容器提供了多种创建方法,下面介绍几种常用的。 & a1 M1 ~) {$ _/ [0 `7 R 创建一个Widget类型的空的vector对象: 5 e7 w# S( r+ C' j+ y' p vector<Widget> vWidgets; 创建一个包含500个Widget类型数据的vector: ) n! b) c6 `, n" @9 L) i! H vector<Widget> vWidgets(500); " R/ j& u& a5 ]% Y3 J+ @( L, u 创建一个包含500个Widget类型数据的vector,并且都初始化为0: vector<Widget> vWidgets(500, Widget(0)); 创建一个Widget的拷贝: * Z# Q0 w9 A- d; _9 ?1 ` vector<Widget> vWidgetsFromAnother(vWidgets); 向vector添加一个数据 ! `- n+ L) L2 ~8 ^% A/ b$ A vector添加数据的缺省方法是push_back()。push_back()函数表示将数据添加到vector的尾部,并按需要来分配内存。例如:向vector<Widget>中添加10个数据,需要如下编写代码: for(int i= 0;i<10; i++) { vWidgets.push_back(Widget(i)); }4 C. v% w+ j2 R" c' j) P 获取vector中制定位置的数据 & S# R4 c- U# g0 q( a7 K vector里面的数据是动态分配的,使用push_back()的一系列分配空间常常决定于文件或一些数据源。如果想知道vector存放了多少数据,可以使用empty()。获取vector的大小,可以使用size()。例如,如果想获取一个vector v的大小,但不知道它是否为空,或者已经包含了数据,如果为空想设置为-1,你可以使用下面的代码实现: int nSize = v.empty() ? -1 : static_cast<int>(v.size()); 访问vector中的数据! A& i7 f9 n, ^8 Z6 w) y 使用两种方法来访问vector。 1、 vector::at(); K5 ?# }/ @* F! d2 ? 2、 vector: perator[]operator[]主要是为了与C语言进行兼容。它可以像C语言数组一样操作。但at()是我们的首选,因为at()进行了边界检查,如果访问超过了vector的范围,将抛出一个例外。由于operator[]容易造成一些错误,所有我们很少用它,下面进行验证一下: 分析下面的代码: vector<int> v;6 a# x, Z' C4 ~' ~ v.reserve(10); for(int i=0; i<7; i++) { v.push_back(i);! ~& w# O6 Q, _. B }2 O/ |0 f* s9 {* w4 F m$ k/ K4 C try {int iVal1 = v[7];! x, D- R3 P% U9 D // not bounds checked - will not throw! x9 S5 I2 ~3 s) g( h int iVal2 = v.at(7);- S( N- K* }/ r // bounds checked - will throw if out of range } catch(const exception& e) {" w! R% k7 y$ l. M6 d E cout << e.what(); } 删除vector中的数据 vector能够非常容易地添加数据,也能很方便地取出数据,同样vector提供了erase(),pop_back(),clear()来删除数据,当删除数据时,应该知道要删除尾部的数据,或者是删除所有数据,还是个别的数据。 ! q4 q j) j, h4 l6 d) U* j2 W Remove_if()算法 如果要使用remove_if(),需要在头文件中包含如下代码::9 Y6 f# C& ]1 `4 q* |, _/ F# d #include <algorithm> Remove_if()有三个参数:9 ?* a% S- I) V9 J: | 1、 iterator _First:指向第一个数据的迭代指针。 2、 iterator _Last:指向最后一个数据的迭代指针。3 a( k% X8 u5 H! I. r' r X 3、 predicate _Pred:一个可以对迭代操作的条件函数。1 P% Q6 C/ w3 C# @3 Q 6 i( Y+ o x1 l% r' z 0 _( v& d$ T8 u7 Z G% j" a 条件函数 " p& h- M0 w5 V1 C ( {- R& q& ~- ~, n 条件函数是一个按照用户定义的条件返回是或否的结果,是最基本的函数指针,或是一个函数对象。这个函数对象需要支持所有的函数调用操作,重载operator()()操作。remove_if()是通过unary_function继承下来的,允许传递数据作为条件。 % x. \/ |7 w' M) z 例如,假如想从一个vector<CString>中删除匹配的数据,如果字串中包含了一个值,从这个值开始,从这个值结束。首先应该建立一个数据结构来包含这些数据,类似代码如下: #include <functional> enum findmodes { FM_INVALID = 0,6 }* ]% a2 s X3 w% t% a% {# J+ O FM_IS, FM_STARTSWITH, FM_ENDSWITH, FM_CONTAINS }; typedef struct tagFindStr { UINT iMode; CString szMatchStr;4 p! M" A' n3 }% Y3 n } FindStr;5 l; n2 |, ~# S9 a( g typedef FindStr* LPFINDSTR; 然后处理条件判断: class FindMatchingString : public std::unary_function<CString, bool> {) P+ j* ~ C$ L3 R1 D) i public: FindMatchingString(const LPFINDSTR lpFS) :4 p* J$ W. @) {# ?- V m_lpFS(lpFS) { } bool operator()(CString& szStringToCompare) const {$ u( @1 A: b8 k. b, [5 r bool retVal = false; switch (m_lpFS->iMode) { case FM_IS: {) ?( ?# t. i& P3 F1 r: N retVal = (szStringToCompare == m_lpFDD->szMatchStr);, w+ H7 U+ [% ^( @ break;1 H* |/ L9 R; ^( b' m }7 J# d( r- y, G8 x case FM_STARTSWITH: { retVal = (szStringToCompare.Left(m_lpFDD->szMatchStr.GetLength())% b) e9 t0 t- j# Q == m_lpFDD->szWindowTitle); break; } case FM_ENDSWITH: {' \: t; m+ g, ] j0 |# P$ V( r6 M retVal = (szStringToCompare.Right(m_lpFDD->szMatchStr.GetLength()) == m_lpFDD->szMatchStr); break;2 W3 E1 {" F% F& G+ }; C& } }3 D" I! D' f. n0 @7 F case FM_CONTAINS: { retVal = (szStringToCompare.Find(m_lpFDD->szMatchStr) != -1); break; } }$ l% C* b7 Q5 |8 y G* `: e! b9 I return retVal;9 V, _3 F: W+ t } private: LPFINDSTR m_lpFS;+ H. n8 o K/ a C2 M. N }; 通过这个操作你可以从vector中有效地删除数据: FindStr fs;1 }" j3 c6 h$ |1 I7 U: ?6 k* `2 h$ \ fs.iMode = FM_CONTAINS; fs.szMatchStr = szRemove; vs.erase(std::remove_if(vs.begin(), vs.end(), FindMatchingString(&fs)), vs.end()); 9 X3 g) v% i' [: Y $ m/ w9 X- A4 y& r2 r Remove(),remove_if()等所有的移出操作都是建立在一个迭代范围上的,不能操作容器中的数据。所以在使用remove_if(),实际上操作的时容器里数据的上面的。 + A6 Y, }3 k/ ?6 d* {+ Z 看到remove_if()实际上是根据条件对迭代地址进行了修改,在数据的后面存在一些残余的数据,那些需要删除的数据。剩下的数据的位置可能不是原来的数据,但他们是不知道的。 & S5 \! x# V+ v 调用erase()来删除那些残余的数据。注意上面例子中通过erase()删除remove_if()的结果和vs.enc()范围的数据。' t# k- L6 J6 @0 Y / F, O- N9 U! d/ ?7 y5 T$ U8 U |
| 谢谢分享 |
微信公众号
手机版