【1】模板类vector
模板类vector可理解为广义数组。广义数组,即与类型无关的数组,具有与数组相同的所有操作。
那么,你或许要问:既然C++语言本身已提供了一个序列式容器array,为什么还要vector呢?
我们一直强调,事物总是朝向更先进的方向螺旋式发展与进化。这个问题其中的道理也不例外。
vector的数据安排及操作方式与array非常相似。两者唯一区别在于空间运用的灵活性。
array是静态空间,一旦配置不能改变。要想换个大(或小)点的房子,一切琐细得由客户端自己料理(步骤如下):
首先,配置一块新空间,然后从旧地址将元素逐一搬往新地址,最后把原来的空间释放还给系统。
vector是动态空间,不仅可以在运行期再确定容器容量大小,而且随着元素的加入,它的内部机制会自动扩充空间以容纳新元素。
所以,相比较array,运用vector对内存的合理灵活性利用有很大的帮助。
【2】vector应用实例
(1)有构造函数才会有容器。模板类vector的构造函数及构建实例。代码如下:
1 #include <iostream>
2 #include <vector>
3 #include <memory>
4 using namespace std;
5
6 void main()
7 {
8 /* C++11
9 default (1)
10 explicit vector (const allocator_type& alloc = allocator_type());
11 // 构建一个空容器(默认构造函数)。
12
13 fill (2)
14 explicit vector (size_type n);
15 vector (size_type n, const value_type& val,
16 const allocator_type& alloc = allocator_type());
17 // 构建一个容器。容器存储n个元素,每个元素的初始值为val(如果提供)。
18
19 range (3)
20 template <class InputIterator>
21 vector (InputIterator first, InputIterator last,
22 const allocator_type& alloc = allocator_type());
23 // 构建一个容器。容器存储元素与源容器中[first,last)区间的元素内容一样。
24 // 内容指存放元素的值及位置和[first,last)区间中完全一样,方向也要一致。
25
26 copy (4)
27 vector (const vector& x);
28 vector (const vector& x, const allocator_type& alloc);
29 // 拷贝构造函数。构建一个容器,逐个复制源容器x中的每一个元素,存放到本容器中,方向也保持一致。
30
31 move (5)
32 vector (vector&& x);
33 vector (vector&& x, const allocator_type& alloc);
34 // 移动构造函数。如果新的分配器alloc和x的分配器alloc不一样,那么将移动源容器x里面的元素到新的vector。
35 // 如果分配器是一样的,那么将直接转换其所有权。
36 // 将右值引用中容器x所有元素的所有权移动到新的vector中,避免付出昂贵的复制代价。
37
38 initializer list (6)
39 vector (initializer_list<value_type> il,
40 const allocator_type& alloc = allocator_type());
41 // 初始化列表构造函数。从初始化列表il中复制每一个元素,放到新的vector中,方向与列表保持一致。
42 */
43 // default (1)
44 vector<int> vInt1;
45
46 // fill (2)
47 int n;
48 cin >> n;
49 vector<int> vInt2(n);
50
51 vector<int> vInt3(10);
52
53 vector<int> vInt4(10, 100);
54
55 // range(3)
56 vector<int> vInt5(vInt4.begin(), vInt4.end());
57
58 int myInt[] = {1, 2, 3, 4, 5};
59 vector<int> vInt6(myInt, myInt + sizeof(myInt) / sizeof(int));
60
61 // copy(4)
62 vector<int> vInt7(vInt4);
63
64 // move(5)
65 vector<unique_ptr<string> > vUS = vector<unique_ptr<string> >({
66 unique_ptr<string> (new string("Qin")),
67 unique_ptr<string> (new string("Liu")),
68 unique_ptr<string> (new string("Wang")),
69 unique_ptr<string> (new string("Zhang"))});
70
71 // initializer_list(6)
72 vector<int> vInt8({10, 20, 30, 40, 50});
73 }
对于任何一个类而言,构造函数是相当重要的,其所有对象呈现的操作方法都与构造函数息息相关。
类的构造函数为对象先天性的行为铺垫(比如:类的构造函数若多一个参数,那么类将会有很多成员方法为这个参数服务)。
下面的实例演示使用vector模板方便创建动态分配数组的优势(内置数组无法完成)
1 #include <iostream>
2 #include <vector>
3 #include <string>
4 using namespace std;
5
6 void main()
7 {
8 cout << "请输入预处理学生数目:n";
9 int nStudents;
10 cin >> nStudents;
11 vector<string> names(nStudents);
12 vector<int> scores(nStudents);
13 cout << "请输入" << nStudents << " 个学生的姓名和英语成绩 (0 ~ 100)。n";
14 int i;
15 for (i = 0; i < nStudents; ++i)
16 {
17 cout << "姓名 No" << i + 1 << ": ";
18 cin >> names[i];
19 cout << "成绩 (0 ~ 100):";
20 cin >> scores[i];
21 cin.get();
22 }
23 cout << "输入所有学生信息结束。n";
24 cout << "打印输入姓名及成绩如下:n";
25 for (i = 0; i < nStudents; ++i)
26 {
27 cout << names[i] << "t" << scores[i] << endl;
28 }
29
30 cin.get();
31 }
32 // Run out:
33 /*
34 请输入预处理学生数目:
35 5
36 请输入5 个学生的姓名和英语成绩 (0 ~ 100)。
37 姓名 No1: sun
38 成绩 (0 ~ 100):89
39 姓名 No2: li
40 成绩 (0 ~ 100):87
41 姓名 No3: wang
42 成绩 (0 ~ 100):90
43 姓名 No4: qin
44 成绩 (0 ~ 100):98
45 姓名 No5: zhang
46 成绩 (0 ~ 100):69
47 输入所有学生信息结束。
48 打印输入姓名及成绩如下:
49 sun 89
50 li 87
51 wang 90
52 qin 98
53 zhang 69
54 */
vector模板更多的方法请看下节。
(2)常用成员方法应用示例如下代码:
1 #include <iostream>
2 #include <vector>
3 using namespace std;
4
5 void printVectorValue(vector<int> & vInt)
6 {
7 for (vector<int>::iterator pt = vInt.begin(); pt != vInt.end(); ++pt)
8 {
9 cout << *pt << "t";
10 }
11 cout << endl;
12 }
13
14 void main()
15 {
16 // vector对象的常用方法以及应用示例如下:
17 cout << "动态构建一个整型容器(请输入整数值,0时退出):n";
18 vector<int> vMyInts;
19 int nTemp;
20 while (cin >> nTemp && nTemp != 0)
21 {
22 vMyInts.push_back(nTemp);
23 }
24 cout << "您输入 " << vMyInts.size() << "个元素,分别如下: " << endl;
25 printVectorValue(vMyInts);
26 cout << "构建整型容器vMyInts完成" << endl << endl;
27
28 //(1)a.assign(b.begin(), b.begin() + 3); // b为向量,将b的0~2个元素构成的向量赋给a
29 cout << "(1) assign方法 :" << endl;
30 vector<int> vA1;
31 vA1.assign(vMyInts.begin(), vMyInts.begin() + 3);
32 cout << "容器vA1元素如下:" << endl;
33 printVectorValue(vA1);
34 cout << "(1) assign方法应用示例完成。" << endl << endl;
35
36 //(2)a.assign(4, 2); // 容器a只含4个元素,且每个元素值为2
37 cout << "(2) assign(4, 2)方法 :" << endl;
38 vector<int> vA2;
39 vA2.assign(4, 12);
40 cout << "容器vA2元素如下:" << endl;
41 printVectorValue(vA2);
42 cout << "(2) assign(4, 2)方法应用示例完成。" << endl << endl;
43
44 //(3)a.back(); // 返回容器a的最后一个元素
45 cout << "(3) back方法 :" << endl;
46 cout << "vMyInts容器的最后一个元素是:" << vMyInts.back() << endl;
47 cout << "(3) back方法应用示例完成。" << endl << endl;
48
49 // (4)a.front(); // 返回容器a的第一个元素
50 cout << "(4) front方法 :" << endl;
51 cout << "vMyInts容器的最前一个元素是:" << vMyInts.front() << endl;
52 cout << "(4) front方法应用示例完成。" << endl << endl;
53
54 // (5)a[i]; // 返回a的第i个元素,当且仅当a[i]存在
55 cout << "(5) a[i] 方法 :" << endl;
56 cout << "vMyInts容器的第2个元素是:" << vMyInts[2 - 1] << endl;
57 cout << "(5) a[i]方法应用示例完成。" << endl << endl;
58
59 // (6)a.clear(); // 清空容器a中的元素
60 cout << "(6) clear() 方法 :" << endl;
61 cout << "清空前,vA2容器中的元素为: " << endl;
62 printVectorValue(vA2);
63 vA2.clear();
64 cout << "清空后,vA2容器中的元素为: " << endl;
65 printVectorValue(vA2);
66 cout << "(6) clear()方法应用示例完成。" << endl << endl;
67
68 // (7)a.empty(); // 判断容器a是否为空,空则返回ture,不空则返回false
69 cout << "(7) empty() 方法 :" << endl;
70 cout << "vA2容器是否为空:" << vA2.empty() << endl;
71 cout << "(7) empty()方法应用示例完成。" << endl << endl;
72
73 // (8)a.pop_back(); // 删除容器a的最后一个元素
74 cout << "(8) pop_back() 方法 :" << endl; vA2.clear();
75 cout << "删除前,vMyInts容器中的元素为: " << endl;
76 printVectorValue(vMyInts);
77 vMyInts.pop_back();
78 cout << "删除最后一个元素后,vMyInts容器中的元素为: " << endl;
79 printVectorValue(vMyInts);
80 cout << "(8) pop_back()方法应用示例完成。" << endl << endl;
81
82 // (9)a.erase(a.begin() + 1, a.begin() + 3);
83 // 删除容器a中第1个(从第0个算起)到第2个元素,也就是说删除的元素从[a.begin() + 1, a.begin() + 3)(前闭后开区间)
84 cout << "(9) erase() 方法 :" << endl; vA2.clear();
85 cout << "删除前,vMyInts容器中的元素为: " << endl;
86 printVectorValue(vMyInts);
87 vMyInts.erase(vMyInts.begin() + 1, vMyInts.begin() + 3);
88 cout << "删除后,vMyInts容器中的元素为: " << endl;
89 printVectorValue(vMyInts);
90 cout << "(9) erase()方法应用示例完成。" << endl << endl;
91
92 // (10)a.push_back(5); // 在容器a的最后一个向量后插入一个元素,其值为5
93 cout << "(10) push_back() 方法 :" << endl; vA2.clear();
94 cout << "添加前,vMyInts容器中的元素为: " << endl;
95 printVectorValue(vMyInts);
96 vMyInts.push_back(99);
97 cout << "添加后,vMyInts容器中的元素为: " << endl;
98 printVectorValue(vMyInts);
99 cout << "(10) push_back()方法应用示例完成。" << endl << endl;
100
101 // (11)a.insert(a.begin() + 1, 5);
102 // 在容器a的第1个元素(从第0个算起)的位置插入数值5,如a为1,2,3,4 插入元素后为1,5,2,3,4
103 cout << "(11) insert() 方法 :" << endl;
104 cout << "插入前,vMyInts容器中的元素为: " << endl;
105 printVectorValue(vMyInts);
106 vMyInts.insert(vMyInts.begin() + 1, 11);
107 cout << "插入后,vMyInts容器中的元素为: " << endl;
108 printVectorValue(vMyInts);
109 cout << "(11) insert()方法应用示例完成。" << endl << endl;
110
111 // (12)a.insert(a.begin() + 1, 3, 5); // 在容器a的第1个元素(从第0个算起)的位置插入3个数,其值都为5
112 cout << "(12) insert() 方法 :" << endl;
113 cout << "插入前,vMyInts容器中的元素为: " << endl;
114 printVectorValue(vMyInts);
115 vMyInts.insert(vMyInts.begin() + 1, 2, 12);
116 cout << "插入后,vMyInts容器中的元素为: " << endl;
117 printVectorValue(vMyInts);
118 cout << "(12) insert()方法应用示例完成。" << endl << endl;
119
120 // (13)a.insert(a.begin() + 1, b + 3, b + 6);
121 // b为数组。在a的第1个元素(从第0个算起)的位置插入b的第3个元素到第5个元素(不包括b + 6)
122 // b为1,2,3,4,5,9,8 插入元素后为1,4,5,9,2,3,4,5,9,8
123 cout << "(13) insert() 方法 (容器示例):" << endl;
124 cout << "插入前,vMyInts容器中的元素为: " << endl;
125 printVectorValue(vMyInts);
126 cout << "插入前,vA1容器中的元素为: " << endl;
127 printVectorValue(vA1);
128 vA1.insert(vA1.begin() + 1, vMyInts.begin() + 3, vMyInts.begin() + 6);
129 cout << "插入后,vMyInts容器中的元素为: " << endl;
130 printVectorValue(vMyInts);
131 cout << "插入后,vA1容器中的元素为: " << endl;
132 printVectorValue(vA1);
133 cout << "(13) insert()方法应用示例完成。" << endl << endl;
134
135 cout << "(13) insert() 方法 (数组示例):" << endl;
136 cout << "插入前,vA1容器中的元素为: " << endl;
137 printVectorValue(vA1);
138 cout << "数组中的元素为: {1, 2, 3, 4, 5, 6}" << endl;
139 int nArrB[] = {1, 2, 3, 4, 5, 6};
140 vA1.insert(vA1.begin() + 1, nArrB + 1, nArrB + 4);
141 cout << "插入后,vA1容器中的元素为: " << endl;
142 printVectorValue(vA1);
143 cout << "(13) insert()方法应用示例完成。" << endl << endl;
144
145 // (14)a.size(); // 返回容器a中元素的个数;
146 cout << "(14) size() 方法: " << endl;
147 cout << "vA1容器中的元素为: " << endl;
148 printVectorValue(vA1);
149 cout << "vA1容器中元素个数为:" << vA1.size() << endl;
150 cout << "(14) size()方法应用示例完成。" << endl << endl;
151
152 // (15)a.capacity(); // 返回容器a的容量
153 cout << "(15) capacity() 方法: " << endl;
154 cout << "vA1容器的容量为:" << vA1.capacity() << endl;
155 cout << "(15) capacity()方法应用示例完成。" << endl << endl;
156
157 // (16)a.rezize(10); // 将a的现有元素个数调至10个,多则删,少则补,其值随机
158 cout << "(16) resize() 方法: " << endl;
159 cout << "重新分配大小前,vA1容器中元素为: " << endl;
160 printVectorValue(vA1);
161 vA1.resize(6);
162 cout << "vA1.resize(6) 重新分配大小后,vA1容器中元素为:" << endl;
163 printVectorValue(vA1);
164 cout << "(16) resize()方法应用示例完成。" << endl << endl;
165
166 // (17)a.rezize(10, 2); // 将容器a的现有元素个数调至10个,多则删,少则补其值为2
167 cout << "(17) resize() 方法: " << endl;
168 cout << "重新分配大小前,vA1容器中元素为: " << endl;
169 printVectorValue(vA1);
170 vA1.resize(10, 100);
171 cout << "vA1.resize(10, 110) 重新分配大小后,vA1容器中元素为:" << endl;
172 printVectorValue(vA1);
173 cout << "(17) resize()方法应用示例完成。" << endl << endl;
174
175 // (18)a.reserve(100);
176 // 将容器a的容量(capacity)扩充至100,也就是说现在测试 a.capacity();的时候返回值是100。
177 // 这种操作只有在需要给a添加大量数据的时候才有意义,
178 // 因为这将避免内存多次容量扩充操作(当a的容量不足时电脑会自动扩容,当然这必然降低性能。)
179 cout << "(18) reserve() 方法: " << endl;
180 cout << "扩容前,vA1容器的容量为:" << vA1.capacity() << endl;
181 vA1.reserve(30);
182 cout << "扩容后,vA1容器的容量为:" << vA1.capacity() << endl;
183 cout << "(18) reserve()方法应用示例完成。" << endl << endl;
184
185 // (19)a.swap(b); // b为容器,将a中的元素和b中的元素进行整体性交换
186 cout << "(19) swap() 方法: " << endl;
187 cout << "vA1容器中的元素为: " << endl;
188 printVectorValue(vA1);
189 cout << "vMyInts容器中的元素为: " << endl;
190 printVectorValue(vMyInts);
191 vA1.resize(5);
192 vMyInts.resize(5);
193 vA1.swap(vMyInts);
194 cout << "vA1容器中的元素为: " << endl;
195 printVectorValue(vA1);
196 cout << "vMyInts容器中的元素为: " << endl;
197 printVectorValue(vMyInts);
198 cout << "(19) swap() 方法应用示例完成。 " << endl << endl;
199
200 // (20)a = b; // b为容器,将一个对象赋给另一个对象
201 cout << "(20) 赋值方法: " << endl;
202 cout << "vA1容器中的元素为: " << endl;
203 printVectorValue(vA1);
204 vector<int> vTemp = vA1;
205 cout << " vTemp = vA1 后,vTemp 容器中的元素为: " << endl;
206 printVectorValue(vTemp);
207 cout << "(20) 赋值方法应用示例完成。 " << endl << endl;
208
209 // (20)a == b; // b为容器,向量的比较操作还有!=,>=,<=,>,<
210 cout << "(21) 比较操作: " << endl;
211 cout << "vA1容器中的元素为: " << endl;
212 printVectorValue(vA1);
213 cout << " vTemp 容器中的元素为: " << endl;
214 printVectorValue(vTemp);
215 cout << "vA1 == vTemp 比较:" << (vA1 == vTemp) << endl;
216 cout << "(21) 比较操作应用示例完成。 " << endl << endl;
217 cin >> nTemp;
218 }
219 // Run out
220 /*
221 动态构建一个整型容器(请输入整数值,0时退出):
222 12
223 23
224 34
225 45
226 56
227 67
228 78
229 89
230 90
231 0
232 您输入 9个元素,分别如下:
233 12 23 34 45 56 67 78 89 90
234 构建整型容器vMyInts完成
235
236 (1) assign方法 :
237 容器vA1元素如下:
238 12 23 34
239 (1) assign方法应用示例完成。
240
241 (2) assign(4, 2)方法 :
242 容器vA2元素如下:
243 12 12 12 12
244 (2) assign(4, 2)方法应用示例完成。
245
246 (3) back方法 :
247 vMyInts容器的最后一个元素是:90
248 (3) back方法应用示例完成。
249
250 (4) front方法 :
251 vMyInts容器的最前一个元素是:12
252 (4) front方法应用示例完成。
253
254 (5) a[i] 方法 :
255 vMyInts容器的第2个元素是:23
256 (5) a[i]方法应用示例完成。
257
258 (6) clear() 方法 :
259 清空前,vA2容器中的元素为:
260 12 12 12 12
261 清空后,vA2容器中的元素为:
262
263 (6) clear()方法应用示例完成。
264
265 (7) empty() 方法 :
266 vA2容器是否为空:1
267 (7) empty()方法应用示例完成。
268
269 (8) pop_back() 方法 :
270 删除前,vMyInts容器中的元素为:
271 12 23 34 45 56 67 78 89 90
272 删除最后一个元素后,vMyInts容器中的元素为:
273 12 23 34 45 56 67 78 89
274 (8) pop_back()方法应用示例完成。
275
276 (9) erase() 方法 :
277 删除前,vMyInts容器中的元素为:
278 12 23 34 45 56 67 78 89
279 删除后,vMyInts容器中的元素为:
280 12 45 56 67 78 89
281 (9) erase()方法应用示例完成。
282
283 (10) push_back() 方法 :
284 添加前,vMyInts容器中的元素为:
285 12 45 56 67 78 89
286 添加后,vMyInts容器中的元素为:
287 12 45 56 67 78 89 99
288 (10) push_back()方法应用示例完成。
289
290 (11) insert() 方法 :
291 插入前,vMyInts容器中的元素为:
292 12 45 56 67 78 89 99
293 插入后,vMyInts容器中的元素为:
294 12 11 45 56 67 78 89 99
295 (11) insert()方法应用示例完成。
296
297 (12) insert() 方法 :
298 插入前,vMyInts容器中的元素为:
299 12 11 45 56 67 78 89 99
300 插入后,vMyInts容器中的元素为:
301 12 12 12 11 45 56 67 78 89 99
302
303 (12) insert()方法应用示例完成。
304
305 (13) insert() 方法 (容器示例):
306 插入前,vMyInts容器中的元素为:
307 12 12 12 11 45 56 67 78 89 99
308
309 插入前,vA1容器中的元素为:
310 12 23 34
311 插入后,vMyInts容器中的元素为:
312 12 12 12 11 45 56 67 78 89 99
313
314 插入后,vA1容器中的元素为:
315 12 11 45 56 23 34
316 (13) insert()方法应用示例完成。
317
318 (13) insert() 方法 (数组示例):
319 插入前,vA1容器中的元素为:
320 12 11 45 56 23 34
321 数组中的元素为: {1, 2, 3, 4, 5, 6}
322 插入后,vA1容器中的元素为:
323 12 2 3 4 11 45 56 23 34
324 (13) insert()方法应用示例完成。
325
326 (14) size() 方法:
327 vA1容器中的元素为:
328 12 2 3 4 11 45 56 23 34
329 vA1容器中元素个数为:9
330 (14) size()方法应用示例完成。
331
332 (15) capacity() 方法:
333 vA1容器的容量为:9
334 (15) capacity()方法应用示例完成。
335
336 (16) resize() 方法:
337 重新分配大小前,vA1容器中元素为:
338 12 2 3 4 11 45 56 23 34
339 vA1.resize(6) 重新分配大小后,vA1容器中元素为:
340 12 2 3 4 11 45
341 (16) resize()方法应用示例完成。
342
343 (17) resize() 方法:
344 重新分配大小前,vA1容器中元素为:
345 12 2 3 4 11 45
346 vA1.resize(10, 110) 重新分配大小后,vA1容器中元素为:
347 12 2 3 4 11 45 100 100 100 100
348
349 (17) resize()方法应用示例完成。
350
351 (18) reserve() 方法:
352 扩容前,vA1容器的容量为:13
353 扩容后,vA1容器的容量为:30
354 (18) reserve()方法应用示例完成。
355
356 (19) swap() 方法:
357 vA1容器中的元素为:
358 12 2 3 4 11 45 100 100 100 100
359
360 vMyInts容器中的元素为:
361 12 12 12 11 45 56 67 78 89 99
362
363 vA1容器中的元素为:
364 12 12 12 11 45
365 vMyInts容器中的元素为:
366 12 2 3 4 11
367 (19) swap() 方法应用示例完成。
368
369 (20) 赋值方法:
370 vA1容器中的元素为:
371 12 12 12 11 45
372 vTemp = vA1 后,vTemp 容器中的元素为:
373 12 12 12 11 45
374 (20) 赋值方法应用示例完成。
375
376 (21) 比较操作:
377 vA1容器中的元素为:
378 12 12 12 11 45
379 vTemp 容器中的元素为:
380 12 12 12 11 45
381 vA1 == vTemp 比较:1
382 (21) 比较操作应用示例完成。
383 */
类的成员方法应用示例运行结果如下:
这么多成员方法,为什么没有sort排序方法呢?
(3)通用成员函数。上面常用方法那么多,怎么没有排序方法呢?这点得追溯于STL的设计理念(尽可能一劳永逸)。
STL从更广泛的角度定义了非成员函数来执行这些操作,即不是为每个类都定义sort()成员函数,而是定义一个适用于所有容器类的非成员函数sort()。
试想一个问题,假设有10个类,每个类都支持10种操作,若每个类都有自己的成员函数,则需要定义100(10*10)个成员函数。而采用STL方式,只需要定义10个非成员函数即可。
另外需要注意,已有执行相同任务的非成员函数,STL有时还会为类定义一个成员函数,因为对于有些操作来说,类特定算法的效率比通用算法高。
下面学习几个所谓的公用函数:for_each()、random_shuffle()、sort()。
3.1 for_each函数接受3个参数,前两个是定义容器中区间的迭代器,最后一个是指向函数的指针。可以用for_each函数来代替for循环。例如:
1 #include <iostream>
2 #include <vector>
3 #include <algorithm> // for_each
4 using namespace std;
5
6 void printVectorValue(int & rInt)
7 {
8 cout << rInt << "t";
9 }
10
11 void main()
12 {
13 cout << "动态构建一个整型容器(请输入整数值,0时退出):n";
14 vector<int> vMyInts;
15 int nTemp;
16 while (cin >> nTemp && nTemp != 0)
17 {
18 vMyInts.push_back(nTemp);
19 }
20 cout << "您输入 " << vMyInts.size() << " 个元素,分别如下: " << endl;
21 cout << "使用for循环打印容器元素如下:" << endl;
22 for (vector<int>::iterator pIt = vMyInts.begin(); pIt != vMyInts.end(); ++pIt)
23 {
24 cout << *pIt << "t";
25 }
26 cout << endl << "使用for_each打印容器元素如下:" << endl;
27 for_each(vMyInts.begin(), vMyInts.end(), printVectorValue);
28 cout << endl << "构建整型容器vMyInts完成" << endl << endl;
29 cin >> nTemp;
30 }
31 // Run out
32 /*
33 动态构建一个整型容器(请输入整数值,0时退出):
34 12
35 23
36 34
37 45
38 56
39 67
40 78
41 89
42 90
43 0
44 您输入 9 个元素,分别如下:
45 使用for循环打印容器元素如下:
46 12 23 34 45 56 67 78 89 90
47 使用for_each打印容器元素如下:
48 12 23 34 45 56 67 78 89 90
49 构建整型容器vMyInts完成
50 */
这样可以避免显式使用迭代器变量。
3.2 random_shffle函数接受两个指定区间的迭代器参数,并随机排列该区间中的元素。应用示例代码如下:
1 #include <iostream>
2 #include <vector>
3 #include <string>
4 #include <algorithm> // for_each
5 using namespace std;
6
7 template<class T>
8 void printVectorValue(T & rInt)
9 {
10 cout << rInt << "t";
11 }
12
13 void main()
14 {
15 cout << "动态构建一个整型容器(请输入整数值,0时退出):n";
16 vector<int> vMyInts;
17 int nTemp;
18 while (cin >> nTemp && nTemp != 0)
19 {
20 vMyInts.push_back(nTemp);
21 }
22 cout << "您输入 " << vMyInts.size() << " 个元素,分别如下: " << endl;
23 cout << "使用for_each打印排序前容器元素如下:" << endl;
24 for_each(vMyInts.begin(), vMyInts.end(), printVectorValue<int>);
25 random_shuffle(vMyInts.begin(), vMyInts.end());
26 cout << endl << "使用for_each打印排序后容器元素如下:" << endl;
27 for_each(vMyInts.begin(), vMyInts.end(), printVectorValue<int>);
28
29 cout << endl;
30 vector<string> vStr;
31 vStr.push_back("sun");
32 vStr.push_back("zhang");
33 vStr.push_back("huang");
34 vStr.push_back("liu");
35 vStr.push_back("qin");
36 cout << endl << "打印排序前容器元素如下:" << endl;
37 for (int j = 0; j < vStr.size(); ++j)
38 {
39 cout << vStr[j].c_str() << "t";
40 }
41 std::random_shuffle(vStr.begin(), vStr.end()); // 迭代器
42 cout << endl << "打印排序后容器元素如下:" << endl;
43 for (int j = 0; j < vStr.size(); ++j)
44 {
45 cout << vStr[j].c_str() << "t";
46 }
47 cout << endl;
48 system("pause");
49 }
程序运行结果如下:
3.3 sort函数也要求容器支持随机访问,该函数有两个版本:
第一个版本接受两个定义区间的迭代器参数,并使用为存储在容器中的类型元素定义的<运算符。
备注:如果元素为用户自定义类型,必须定义能够处理该类型对象的operator<()函数),对区间中的元素进行操作。
第二个版本接受3个参数,前两个参数也是指定区间的迭代器,最后一个参数是指向要使用的函数的指针(而不是比较的operator<()运算符)。
sort函数的应用示例代码如下:
1 #include <iostream>
2 #include <vector>
3 #include <string>
4 #include <algorithm> // for_each
5 using namespace std;
6
7 template<class T>
8 void printVectorValue(T & rInt)
9 {
10 cout << rInt << "t";
11 }
12
13 struct student
14 {
15 string strName;
16 int nAge;
17
18 student(string sName = "liu", int nAge = 22) : strName(sName), nAge(nAge)
19 {}
20 };
21
22 bool worseThan(const student & stuObject1, const student & stuObject2)
23 {
24 if (stuObject1.nAge > stuObject2.nAge)
25 {
26 return true;
27 }
28 else if (stuObject1.nAge == stuObject2.nAge
29 && stuObject1.strName > stuObject2.strName)
30 {
31 return true;
32 }
33 else
34 {
35 return false;
36 }
37 }
38
39 void printValue(const student & rStuObject)
40 {
41 cout << rStuObject.strName << " " << rStuObject.nAge << "n";
42 }
43
44 void main()
45 {
46 cout << "sort函数版本1测试程序:" << endl;
47 cout << "动态构建一个整型容器(请输入整数值,0时退出):n";
48 vector<int> vMyInts;
49 int nTemp;
50 while (cin >> nTemp && nTemp != 0)
51 {
52 vMyInts.push_back(nTemp);
53 }
54 cout << "您输入 " << vMyInts.size() << " 个元素,分别如下: " << endl;
55 cout << "使用for_each打印排序前容器元素如下:" << endl;
56 for_each(vMyInts.begin(), vMyInts.end(), printVectorValue<int>);
57 sort(vMyInts.begin(), vMyInts.end()); // 版本1
58 cout << endl << "使用for_each打印排序后容器元素如下:" << endl;
59 for_each(vMyInts.begin(), vMyInts.end(), printVectorValue<int>);
60
61 cout << endl << endl << "sort函数版本2测试程序:" << endl;
62 vector<student> vStudents;
63 vStudents.push_back(student("sun", 23));
64 vStudents.push_back(student("zhang", 24));
65 vStudents.push_back(student("huang", 22));
66 vStudents.push_back(student("liu", 21));
67 vStudents.push_back(student("qin", 22));
68 cout << "使用for_each打印排序前容器元素如下:" << endl;
69 for_each(vStudents.begin(), vStudents.end(), printValue);
70 sort(vStudents.begin(), vStudents.end(), worseThan); // 版本2
71 cout << "使用for_each打印排序后容器元素如下:" << endl;
72 for_each(vStudents.begin(), vStudents.end(), printValue);
73 cout << endl;
74 system("pause");
75 }
程序运行结果如下:
通用非成员函数结束。
【3】学习《STL源码剖析》中vector
(1)vector容器可以自动扩充内存空间,具体的扩充规则测试代码如下:
1 #include <vector>
2 #include <iostream>
3 #include <algorithm>
4 using namespace std;
5
6 template<class T>
7 void printVectorValue(T & rInt)
8 {
9 cout << rInt << " ";
10 }
11
12 template<class T>
13 void printSizeAndCapacity(vector<T> & oVec)
14 {
15 for_each(oVec.begin(), oVec.end(), printVectorValue<T>);
16 cout << endl << "size = " << oVec.size() << endl;
17 cout << "capacity = " << oVec.capacity() << endl << endl;
18 }
19
20 int main()
21 {
22 vector<int> iv(2, 9);
23 printSizeAndCapacity(iv);
24 for (int i = 0; i < 8; ++i)
25 {
26 iv.push_back(i + 1);
27 printSizeAndCapacity<int>(iv);
28 }
29
30 system("pause");
31 }
vector容器示意图如下:
运行结果如下:
有一个遗留问题:如size不为零时,扩充后容量应该是之前的2倍,根据上例实际情况,不应该有奇数值的容量!求再探索,作此备录。
(2)vector迭代器和数据结构,如下图所示:
(3)vector部分源码如下:
1 #include<iostream>
2 #include<memory.h>
3 using namespace std;
4
5 // alloc是SGI STL的空间配置器
6 template <class T, class Alloc = alloc>
7 class vector
8 {
9 public:
10 // vector的嵌套类型定义,typedefs用于提供iterator_traits<I>支持
11 typedef T value_type;
12 typedef value_type* pointer;
13 typedef value_type* iterator;
14 typedef value_type& reference;
15 typedef size_t size_type;
16 typedef ptrdiff_t difference_type;
17 protected:
18 // 这个提供STL标准的allocator接口
19 typedef simple_alloc <value_type, Alloc> data_allocator;
20
21 iterator start; // 表示目前使用空间的头
22 iterator finish; // 表示目前使用空间的尾
23 iterator end_of_storage; // 表示实际分配内存空间的尾
24
25 void insert_aux(iterator position, const T& x); // 在position位置插入值为x的元素
26
27 // 释放分配的内存空间
28 void deallocate()
29 {
30 // 由于使用data_allocator进行内存空间的分配,
31 // 所以匹配使用data_allocator::deallocate()进行释放
32 // 如果直接释放, 对于data_allocator内部使用内存池的版本就会发生错误
33 if (start)
34 data_allocator::deallocate(start, end_of_storage - start);
35 }
36
37 void fill_initialize(size_type n, const T& value)
38 {
39 start = allocate_and_fill(n, value);
40 finish = start + n; // 设置当前使用内存空间的结束点
41 // 构造阶段(不多分配内存)
42 // 所以要设置内存空间结束点(与已经使用的内存空间结束点相同)
43 end_of_storage = finish;
44 }
45
46 public:
47 // 获取几种迭代器
48 iterator begin() { return start; }
49 iterator end() { return finish; }
50
51 // 返回当前对象个数
52 size_type size() const { return size_type(end() - begin()); }
53 size_type max_size() const { return size_type(-1) / sizeof(T); }
54 // 返回重新分配内存前最多能存储的对象个数
55 size_type capacity() const { return size_type(end_of_storage - begin()); }
56 // 判空
57 bool empty() const { return begin() == end(); }
58 // 重载[](下标访问)
59 reference operator[](size_type n) { return *(begin() + n); }
60
61 // 默认构造函数。默认构造vector不分配内存空间
62 vector() : start(0), finish(0), end_of_storage(0) {}
63
64 vector(size_type n, const T& value) { fill_initialize(n, value); }
65 vector(int n, const T& value) { fill_initialize(n, value); }
66 vector(long n, const T& value) { fill_initialize(n, value); }
67
68 // 需要对象提供默认构造函数
69 explicit vector(size_type n) { fill_initialize(n, T()); }
70
71 vector(const vector<T, Alloc>& x)
72 {
73 start = allocate_and_copy(x.end() - x.begin(), x.begin(), x.end());
74 finish = start + (x.end() - x.begin());
75 end_of_storage = finish;
76 }
77
78 ~vector()
79 {
80 // 析构对象
81 destroy(start, finish);
82 // 释放内存
83 deallocate();
84 }
85
86 vector<T, Alloc>& operator=(const vector<T, Alloc>& x);
87
88 // 提供访问函数
89 reference front() { return *begin(); }
90 reference back() { return *(end() - 1); }
91
92 ////////////////////////////////////////////////////////////////////////////////
93 // 向容器尾追加一个元素, 可能导致内存重新分配(开辟新空间、移动原数据、释放原内存)
94 ////////////////////////////////////////////////////////////////////////////////
95 // push_back(const T& x)
96 // |
97 // |---------------- 容量已满?
98 // |
99 // ----------------------------
100 // No | | Yes
101 // | |
102 // ↓ ↓
103 // construct(finish, x); insert_aux(end(), x);
104 // ++finish; |
105 // |------ 内存不足, 重新分配
106 // | 大小为原来的2倍
107 // new_finish = data_allocator::allocate(len); <stl_alloc.h>
108 // uninitialized_copy(start, position, new_start); <stl_uninitialized.h>
109 // construct(new_finish, x); <stl_construct.h>
110 // ++new_finish;
111 // uninitialized_copy(position, finish, new_finish); <stl_uninitialized.h>
112 ////////////////////////////////////////////////////////////////////////////////
113
114 void push_back(const T& x)
115 {
116 // 内存满足条件则直接追加元素, 否则需要重新分配内存空间
117 if (finish != end_of_storage)
118 {
119 construct(finish, x);
120 ++finish;
121 }
122 else
123 insert_aux(end(), x);
124 }
125
126
127 ////////////////////////////////////////////////////////////////////////////////
128 // 在指定位置插入元素
129 ////////////////////////////////////////////////////////////////////////////////
130 // insert(iterator position, const T& x)
131 // |
132 // |------------ 容量是否足够 && 是否是end()?
133 // |
134 // -------------------------------------------
135 // No | | Yes
136 // | |
137 // ↓ ↓
138 // insert_aux(position, x); construct(finish, x);
139 // | ++finish;
140 // |-------- 容量是否够用?
141 // |
142 // --------------------------------------------------
143 // Yes | | No
144 // | |
145 // ↓ |
146 // construct(finish, *(finish - 1)); |
147 // ++finish; |
148 // T x_copy = x; |
149 // copy_backward(position, finish - 2, finish - 1); |
150 // *position = x_copy; |
151 // ↓
152 // data_allocator::allocate(len); <stl_alloc.h>
153 // uninitialized_copy(start, position, new_start); <stl_uninitialized.h>
154 // construct(new_finish, x); <stl_construct.h>
155 // ++new_finish;
156 // uninitialized_copy(position, finish, new_finish); <stl_uninitialized.h>
157 // destroy(begin(), end()); <stl_construct.h>
158 // deallocate();
159 ////////////////////////////////////////////////////////////////////////////////
160
161 iterator insert(iterator position, const T& x)
162 {
163 size_type n = position - begin();
164 if (finish != end_of_storage && position == end())
165 {
166 construct(finish, x);
167 ++finish;
168 }
169 else
170 insert_aux(position, x);
171 return begin() + n;
172 }
173
174 iterator insert(iterator position) { return insert(position, T()); }
175
176 void pop_back()
177 {
178 --finish;
179 destroy(finish);
180 }
181
182 iterator erase(iterator position)
183 {
184 if (position + 1 != end())
185 copy(position + 1, finish, position);
186 --finish;
187 destroy(finish);
188 return position;
189 }
190
191
192 iterator erase(iterator first, iterator last)
193 {
194 iterator i = copy(last, finish, first);
195 // 析构掉需要析构的元素
196 destroy(i, finish);
197 finish = finish - (last - first);
198 return first;
199 }
200
201 // 调整size, 但是并不会重新分配内存空间
202 void resize(size_type new_size, const T& x)
203 {
204 if (new_size < size())
205 erase(begin() + new_size, end());
206 else
207 insert(end(), new_size - size(), x);
208 }
209 void resize(size_type new_size) { resize(new_size, T()); }
210
211 void clear() { erase(begin(), end()); }
212
213 protected:
214 // 分配空间, 并且复制对象到分配的空间处
215 iterator allocate_and_fill(size_type n, const T& x)
216 {
217 iterator result = data_allocator::allocate(n);
218 uninitialized_fill_n(result, n, x);
219 return result;
220 }
221
222 // 提供插入操作
223 ////////////////////////////////////////////////////////////////////////////////
224 // insert_aux(iterator position, const T& x)
225 // |
226 // |---------------- 容量是否足够?
227 // ↓
228 // -----------------------------------------
229 // Yes | | No
230 // | |
231 // ↓ |
232 // 从opsition开始, 整体向后移动一个位置 |
233 // construct(finish, *(finish - 1)); |
234 // ++finish; |
235 // T x_copy = x; |
236 // copy_backward(position, finish - 2, finish - 1); |
237 // *position = x_copy; |
238 // ↓
239 // data_allocator::allocate(len);
240 // uninitialized_copy(start, position, new_start);
241 // construct(new_finish, x);
242 // ++new_finish;
243 // uninitialized_copy(position, finish, new_finish);
244 // destroy(begin(), end());
245 // deallocate();
246 ////////////////////////////////////////////////////////////////////////////////
247
248 template <class T, class Alloc>
249 void insert_aux(iterator position, const T& x)
250 {
251 if (finish != end_of_storage) // 还有备用空间
252 {
253 // 在备用空间起始处构造一个元素,并以vector最后一个元素值为其初值
254 construct(finish, *(finish - 1));
255 ++finish;
256 T x_copy = x;
257 copy_backward(position, finish - 2, finish - 1);
258 *position = x_copy;
259 }
260 else // 已无备用空间
261 {
262 const size_type old_size = size();
263 const size_type len = old_size != 0 ? 2 * old_size : 1;
264 // 以上配置元素:如果大小为0,则配置1(个元素大小)
265 // 如果大小不为0,则配置原来大小的两倍
266 // 前半段用来放置原数据,后半段准备用来放置新数据
267
268 iterator new_start = data_allocator::allocate(len); // 实际配置
269 iterator new_finish = new_start;
270 // 将内存重新配置
271 try
272 {
273 // 将原vector的安插点以前的内容拷贝到新vector
274 new_finish = uninitialized_copy(start, position, new_start);
275 // 为新元素设定初值 x
276 construct(new_finish, x);
277 // 调整水位
278 ++new_finish;
279 // 将安插点以后的原内容也拷贝过来
280 new_finish = uninitialized_copy(position, finish, new_finish);
281 }
282 catch(...)
283 {
284 // 回滚操作
285 destroy(new_start, new_finish);
286 data_allocator::deallocate(new_start, len);
287 throw;
288 }
289 // 析构并释放原vector
290 destroy(begin(), end());
291 deallocate();
292
293 // 调整迭代器,指向新vector
294 start = new_start;
295 finish = new_finish;
296 end_of_storage = new_start + len;
297 }
298 }
299
300 ////////////////////////////////////////////////////////////////////////////////
301 // 在指定位置开始连续插入n个值为x的元素
302 ////////////////////////////////////////////////////////////////////////////////
303 // insert(iterator position, size_type n, const T& x)
304 // |
305 // |---------------- 插入元素个数是否为0?
306 // ↓
307 // -----------------------------------------
308 // No | | Yes
309 // | |
310 // | ↓
311 // | return;
312 // |----------- 内存是否足够?
313 // |
314 // -------------------------------------------------
315 // Yes | | No
316 // | |
317 // |------ (finish - position) > n? |
318 // | 分别调整指针 |
319 // ↓ |
320 // ---------------------------- |
321 // No | | Yes |
322 // | | |
323 // ↓ ↓ |
324 // 插入操作, 调整指针 插入操作, 调整指针 |
325 // ↓
326 // data_allocator::allocate(len);
327 // new_finish = uninitialized_copy(start, position, new_start);
328 // new_finish = uninitialized_fill_n(new_finish, n, x);
329 // new_finish = uninitialized_copy(position, finish, new_finish);
330 // destroy(start, finish);
331 // deallocate();
332 ////////////////////////////////////////////////////////////////////////////////
333
334 template <class T, class Alloc>
335 void insert(iterator position, size_type n, const T& x)
336 {
337 // 如果n为0,则不进行任何操作
338 if (n != 0)
339 {
340 if (size_type(end_of_storage - finish) >= n)
341 { // 剩下的备用空间大于等于“新增元素的个数”
342 T x_copy = x;
343 // 以下计算插入点之后的现有元素个数
344 const size_type elems_after = finish - position;
345 iterator old_finish = finish;
346 if (elems_after > n)
347 {
348 // 插入点之后的现有元素个数 大于 新增元素个数
349 uninitialized_copy(finish - n, finish, finish);
350 finish += n; // 将vector 尾端标记后移
351 copy_backward(position, old_finish - n, old_finish);
352 fill(position, position + n, x_copy); // 从插入点开始填入新值
353 }
354 else
355 {
356 // 插入点之后的现有元素个数 小于等于 新增元素个数
357 uninitialized_fill_n(finish, n - elems_after, x_copy);
358 finish += n - elems_after;
359 uninitialized_copy(position, old_finish, finish);
360 finish += elems_after;
361 fill(position, old_finish, x_copy);
362 }
363 }
364 else
365 { // 剩下的备用空间小于“新增元素个数”(那就必须配置额外的内存)
366 // 首先决定新长度:就长度的两倍 , 或旧长度+新增元素个数
367 const size_type old_size = size();
368 const size_type len = old_size + max(old_size, n);
369 // 以下配置新的vector空间
370 iterator new_start = data_allocator::allocate(len);
371 iterator new_finish = new_start;
372 __STL_TRY
373 {
374 // 以下首先将旧的vector的插入点之前的元素复制到新空间
375 new_finish = uninitialized_copy(start, position, new_start);
376 // 以下再将新增元素(初值皆为n)填入新空间
377 new_finish = uninitialized_fill_n(new_finish, n, x);
378 // 以下再将旧vector的插入点之后的元素复制到新空间
379 new_finish = uninitialized_copy(position, finish, new_finish);
380 }
381 # ifdef __STL_USE_EXCEPTIONS
382 catch(...)
383 {
384 destroy(new_start, new_finish);
385 data_allocator::deallocate(new_start, len);
386 throw;
387 }
388 # endif /* __STL_USE_EXCEPTIONS */
389 destroy(start, finish);
390 deallocate();
391 start = new_start;
392 finish = new_finish;
393 end_of_storage = new_start + len;
394 }
395 }
396 }
397 };
(4)使用主要问题及成员函数详解。
4.1 erase函数。vector::erase()方法有两种重载形式:
(1.1)iterator erase (iterator _Where);
(1.2)iterator erase (iterator _First, iterator _Last);
如果是删除指定位置的元素时:返回值是一个迭代器,指向删除元素下一个元素。
如果是删除某范围内的元素时:返回值也表示一个迭代器,指向最后一个删除元素的下一个元素。
请看如下“临床典型性”应用错误示例代码:
1 #include <vector>
2 #include <iostream>
3 #include <algorithm>
4 using namespace std;
5
6 template<class T>
7 void printVectorValue(T & rInt)
8 {
9 cout << rInt << " ";
10 }
11
12 void main()
13 {
14 vector <int> v1;
15 for (int i = 0; i < 6; ++i)
16 {
17 v1.push_back(i + 10);
18 }
19 cout << "(1) v1 容器元素如下:" << endl;
20 for_each(v1.begin(), v1.end(), printVectorValue<int>);
21 cout << endl;
22
23 v1.erase(v1.begin( ));
24 cout << "(2) v1 容器元素如下:" << endl;
25 for_each(v1.begin(), v1.end(), printVectorValue<int>);
26 cout << endl;
27
28 v1.erase(v1.begin( ) + 1, v1.begin( ) + 3);
29 cout << "(3) v1 容器元素如下:" << endl;
30 for_each(v1.begin(), v1.end(), printVectorValue<int>);
31 cout << endl;
32
33 v1.push_back(14);
34 vector<int>::iterator itPt;
35 for (itPt = v1.begin(); itPt != v1.end(); ++itPt)
36 {
37 if (14 == *itPt)
38 {
39 v1.erase(itPt);
40 }
41 }
42
43 system("pause");
44 }
程序运行结果如下:
分析程序:一一遍历容器找到元素值为14,然后一一删除。程序为什么会崩溃呢?
其实,出现这种原因是没搞懂erase的删除原理(套路),当调用erase()后迭代器就失效了,即变成一个野指针。
所以要处理这种问题,关键是要解决调用erase()方法后,迭代器变成野指针的问题。
结合套路,解决这个问题有两种方案:
第一种:正向删除。
第二种:逆向删除。代码如下:
1 #include <vector>
2 #include <iostream>
3 #include <algorithm>
4 using namespace std;
5
6 template<class T>
7 void printVectorValue(T & rInt)
8 {
9 cout << rInt << " ";
10 }
11
12 // 正删
13 template<class T>
14 void eraseAll(vector<T> & v1, T value)
15 {
16 vector<T>::iterator itPt;
17 for (itPt = v1.begin(); itPt != v1.end();)
18 {
19 if (value == *itPt)
20 {
21 itPt = v1.erase(itPt);
22 }
23 else
24 {
25 ++itPt;
26 }
27 }
28 }
29
30 // 逆删
31 template<class T>
32 void eraseAll2(vector<T> & v1, T value)
33 {
34 vector<T>::iterator itPt;
35 for (itPt = --v1.end(); itPt != v1.begin();)
36 {
37 if (value == *itPt)
38 {
39 v1.erase(itPt--);
40 }
41 else
42 {
43 --itPt;
44 }
45 }
46
47 if (value == *itPt)
48 {
49 v1.erase(itPt);
50 }
51 }
52
53 void main()
54 {
55 vector<int> v1(6, 9);
56 for (int i = 0; i < 6; ++i)
57 {
58 v1.push_back(i + 10);
59 }
60 cout << "(1) v1 容器元素如下:" << endl;
61 for_each(v1.begin(), v1.end(), printVectorValue<int>);
62 cout << endl;
63
64 v1.erase(v1.begin( ));
65 cout << "(2) v1 容器元素如下:" << endl;
66 for_each(v1.begin(), v1.end(), printVectorValue<int>);
67 cout << endl;
68
69 v1.erase(v1.begin( ) + 1, v1.begin( ) + 3);
70 cout << "(3) v1 容器元素如下:" << endl;
71 for_each(v1.begin(), v1.end(), printVectorValue<int>);
72 cout << endl;
73
74 v1.insert(v1.begin() + 5, 3, 12);
75 v1.push_back(15);
76 v1.push_back(15);
77 cout << "(4) 删除前 v1 容器元素如下:" << endl;
78 for_each(v1.begin(), v1.end(), printVectorValue<int>);
79 cout << endl;
80
81 // 第一种正向删除
82 eraseAll<int>(v1, 9);
83 eraseAll<int>(v1, 12);
84 eraseAll<int>(v1, 15);
85
86 /* 第二种逆向删除
87 eraseAll2<int>(v1, 9);
88 eraseAll2<int>(v1, 12);
89 eraseAll2<int>(v1, 15);
90 */
91 cout << "(5) 删除9,12,15后 v1 容器元素如下:" << endl;
92 for_each(v1.begin(), v1.end(), printVectorValue<int>);
93 cout << endl;
94 /* 错误删除!!
95 for (itPt = v1.begin(); itPt != v1.end(); ++itPt)
96 {
97 if (14 == *itPt)
98 {
99 v1.erase(itPt);
100 }
101 }
102 */
103
104 system("pause");
105 }
106
107 // Run out
108 /*
109 (1) v1 容器元素如下:
110 9 9 9 9 9 9 10 11 12 13 14 15
111 (2) v1 容器元素如下:
112 9 9 9 9 9 10 11 12 13 14 15
113 (3) v1 容器元素如下:
114 9 9 9 10 11 12 13 14 15
115 (4) 删除前 v1 容器元素如下:
116 9 9 9 10 11 12 12 12 12 13 14 15 15 15
117 (5) 删除9,12,15后 v1 容器元素如下:
118 10 11 13 14
119 请按任意键继续. . .
120 */
规避开失效指针,完全可以正常删除。
为了加深理解,再追加一个正向删除的示例程序:
1 #include <vector>
2 #include <iostream>
3
4 #define PRINT_INFO (1)
5
6 void eraseTarget(std::vector<int>& vect, int value)
7 {
8 auto print = [&]() {
9 for (auto iter = vect.begin(); iter != vect.end();)
10 std::cout << (*iter++) << ((iter == vect.end()) ? std::string{} : " | ");
11 std::cout << std::endl;
12 };
13
14 #if PRINT_INFO
15 std::cout << "************ Begin erase target ************" << std::endl;
16 std::cout << "begin element of vector :: ";
17 print();
18 std::cout << std::endl;
19 #endif
20
21 auto iter = vect.begin();
22 while (iter != vect.end())
23 {
24 #if PRINT_INFO
25 print();
26 std::cout << "before erase current iter value :: " << (*iter) << " || before erase size :: " << vect.size() << std::endl;
27 #endif
28
29 if ((*iter) == value)
30 {
31 iter = vect.erase(iter);
32
33 #if PRINT_INFO
34 std::cout << "after erase current iter value :: " << ((iter == vect.end()) ? (-1) : (*iter))
35 << " || after erase size :: " << vect.size() << std::endl << std::endl;
36 #endif
37 }
38 else
39 {
40 #if PRINT_INFO
41 std::cout << std::endl;
42 #endif
43 ++iter;
44 }
45 }
46
47 #if PRINT_INFO
48 std::cout << "end element of vector :: ";
49 print();
50 std::cout << "************ End erase target ************" << std::endl;
51 #endif
52 }
53
54 int main()
55 {
56 {
57 std::vector<int> vect = { 3, 3, 4, 5, 6, 3, 3, 7, 8, 9, 3, 3 };
58 eraseTarget(vect, 3);
59 }
60
61 return 0;
62 }
备注:可通过宏PRINT_INFO控制是否打印过程信息,便于理解。
附本地运行结果:
4.2 insert函数
insert函数源码如下:
insert函数两种情况分析如下:
insert函数重载多,使用比较方便。
【4】vector总结
相比C++内置的array数组类,vector模板类是有生命的、动态的、可塑性的数组,使用更方便,更健壮。
Good Good Study, Day Day Up.
顺序 选择 循环 总结
原文链接: https://www.cnblogs.com/Braveliu/p/6264543.html
欢迎关注
微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍
原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/247389
非原创文章文中已经注明原地址,如有侵权,联系删除
关注公众号【高性能架构探索】,第一时间获取最新文章
转载文章受原作者版权保护。转载请注明原作者出处!