【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 << "请输入预处理学生数目: "; 9 int nStudents; 10 cin >> nStudents; 11 vector<string> names(nStudents); 12 vector<int> scores(nStudents); 13 cout << "请输入" << nStudents << " 个学生的姓名和英语成绩 (0 ~ 100)。 "; 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 << "输入所有学生信息结束。 "; 24 cout << "打印输入姓名及成绩如下: "; 25 for (i = 0; i < nStudents; ++i) 26 { 27 cout << names[i] << " " << 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 << " "; 10 } 11 cout << endl; 12 } 13 14 void main() 15 { 16 // vector对象的常用方法以及应用示例如下: 17 cout << "动态构建一个整型容器(请输入整数值,0时退出): "; 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 << " "; 9 } 10 11 void main() 12 { 13 cout << "动态构建一个整型容器(请输入整数值,0时退出): "; 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 << " "; 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 << " "; 11 } 12 13 void main() 14 { 15 cout << "动态构建一个整型容器(请输入整数值,0时退出): "; 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() << " "; 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() << " "; 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 << " "; 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 << " "; 42 } 43 44 void main() 45 { 46 cout << "sort函数版本1测试程序:" << endl; 47 cout << "动态构建一个整型容器(请输入整数值,0时退出): "; 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 */
规避开失效指针,完全可以正常删除。
4.2 insert函数
insert函数源码如下:
insert函数两种情况分析如下:
insert函数重载多,使用比较方便。
【4】vector总结
相比C++内置的array数组类,vector模板类是有生命的、动态的、可塑性的数组,使用更方便,更健壮。
Good Good Study, Day Day Up.
顺序 选择 循环 总结