STL泛型编程容器使用注意
1,vector/deque/list 在使用迭代器,删除元素时注意erase()函数的返回值:返回的是指向下一位置的迭代器。
在Visual Studio2019上编辑的示例代码:
#include <iostream>
#include <Windows.h>
#include <vector>
using namespace std;
/*删除元素4*/
int main(void) {
vector<int> IntA;
IntA.push_back(1);
IntA.push_back(2);
IntA.push_back(3);
IntA.push_back(4);
IntA.push_back(4);
IntA.push_back(4);
IntA.push_back(5);
//常规删除
//IntA.erase(IntA.begin()+3);
//采用迭代器删除
vector<int>::iterator it = IntA.begin();
// 此方法错误的使用了迭代器的删除方法
/*
`for (; it != IntA.end(); it++)` {
if (*it == 4) {
IntA.erase(it);
}
}
*/
//此方法正确
for (; it != IntA.end();) {
if (*it == 4) {
it = IntA.erase(it);
}
else {
it++;
}
}
for (int i = 0; i < IntA.size(); i++) {
cout << IntA[i] << endl;
//或者cout << IntA.at(i) << endl;
}
system("pause");
return 0;
}
用注释掉的错误代码,通过编译,但运行会出错,导致程序崩溃
采用正确的方法,编译通过,正常运行,满足要求
解析:
两种版本主要在于如下地方:
for (; it != IntA.end(); it++){ //这里++ 就多余了
if (*it == 4) {
it = IntA.erase(it); //**此处就相当于it++**
}
}
for (; it != IntA.end(); ){ //正确版本
if (*it == 4) {
it = IntA.erase(it);
}
else {
it++;
}
}
2,vector容器使用注意:
(1)vector容器在数据存取的时刻可以使用下标操作和at方法:(还有接口返回的引用方法:front()/back())
v[2] = 100;
v.at(3) = 300;
下标[]和at()方法必须注意越界问题。
(2),当使用vector默认构造函数,还未调用push_back()函数插入数据时,切记不能直接通过下标[]去访问,因为此时vector的size() 和capacity()的值都是0。
3,set和multiset容器使用注意:
(1),set中元素插入过程是按排序规则插入,所以不能指定插入位置。
(2)set不可以直接存取元素。(不可以使用at.(pos)与[]操作符)。
(3)multiset与set的区别:set支持唯一键值,每个元素值只能出现一次;而multiset中同一值可以出现多次。
(4)不可以直接修改set或multiset容器中的元素值,因为该类容器是自动排序的。如果希望修改一个元素值,必须先删除原有的元素,再插入新的元素。
4,map和multimap容器使用注意:
(1),map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。
(2),map支持唯一键值,每个键只能出现一次因此支持[]操作符;而multimap中相同键可以出现多次。multimap不支持[]操作符。
5,list容器使用注意:
list不可以随机存取元素,所以不支持at.(position)函数与[]操作符。可以对其迭代器执行++,但是不能这样操作迭代器:it+3
6,任何时候在模板(template)中使用一个嵌套从属类型名称, 需要在前一个位置, 添加关键字typename。
template<typename T>
void funciton(list<T> val){
typename list<T>::iterator it = val.begin();
}
iterator就是嵌套从属类型名称,前面必须使用typename关键字,不然不能通过编译。