1. 迭代器
迭代器是遍历容器内元素的数据类型,指向容器内某个元素。
2. 迭代器使用
2.1 迭代器定义
vector<int> v = { 1, 2, 3, 4 };
vector<int>::iterator it; // 定义迭代器
2.2 begin和end
vector<int> v = { 1, 2, 3, 4 };
it = v.begin(); // begin()返回指向容器中首个元素的迭代器,该例中指向1
it = v.end(); // end()返回指向容器中末尾元素后面的迭代器,end()指向不存在的元素,该例中指向4后面的位置
// 若容器为空,则begin()和end()返回的迭代器就相同
vector<int> v2;
vector<int>::iterator ibg = v2.begin();
vector<int>::iterator ied = v2.end();
ibg == ied; // true
2.3 使用迭代器遍历
vector<int> v3 = { 1, 2, 3, 4 };
for (vector<int>::iterator it = v3.begin(); it != v3.end(); it++) {
cout << *it << endl;
}
2.4 rbegin和rend
// 反向迭代器:从后往前遍历,rbegin(), rend();
vector<int> v4 = { 1, 2, 3, 4 };
for (vector<int>::reverse_iterator rit = v4.rbegin(); rit != v4.rend(); rit++) {
cout << *rit << endl;
}
2.5 迭代器运算符
a) *it 返回it指向元素的引用,不能对end()位置使用*运算符;
b) it++ 让it指向下一个元素;
c) it-- 让it指向上一个元素;
d) it1 == it2 判断两个迭代器是否相等,即是否指向同一个元素;
e) it->mem, (*it).mem 访问it指向元素中的成员
2.5 const_iterator迭代器
禁止修改迭代器指向的元素。
// const_iterator迭代器,迭代器指向的元素禁止修改
vector<int> v5 = { 1, 2, 3, 4 };
vector<int>::const_iterator it;
for (it = v5.begin(); it != v5.end(); it++) {
*it += 5; // 错误
}
常量容器必须使用const_iterator,否则编译不通过:
const vector<int> v5 = { 1, 2, 3, 4 }; // 常量容器
vector<int>::const_iterator it; // 必须使用const_iterator
for (it = v5.begin(); it != v5.end(); it++) {
}
2.6 cbegin和cend
与begin和end不同的是,cbegin和cend是常量迭代器,禁止修改它们指向的元素。
vector<int> v6 = { 1, 2, 3, 4 };
vector<int>::const_iterator it = v6.cbegin();
for (it; it != v6.cend(); it++) {
*it += 3; // 错误
}
3. 迭代器失效问题
建议操作迭代器过程中,不要改变容器容量(增删元素),否则存在迭代器失效问题。
有如下预防措施:
3.1 建议操作后,立即break
void test() {
vector<int> v = { 1, 2, 3, 4 };
auto it = v.begin();
while (it != v.end()) {
if (*it == 2) {
v.insert(it, 10); // 插入元素
break; // 立即退出
}
it++;
}
for (auto& val : v) {
cout << val << " "; // 1 10 2 3 4
}
}
3.2 操作后立即更新迭代器
示例1:
void test() {
vector<int> v = { 1, 2, 3, 4 };
auto it = v.begin();
int i = 3;
while (it != v.end()) {
it = v.insert(it, i--); // 插入元素后更新it
it++;
if (i == 0) {
break;
}
}
for (auto& val : v) {
cout << val << " "; // 3 2 1 1 2 3 4
}
}
补充:vector的insert函数,在位置i插入元素后返回位置i元素的迭代器。
示例2:
void test() {
vector<int> v = { 1, 2, 3, 4, 5, 6 };
auto it = v.begin();
while (it != v.end()) {
if ((*it) % 2 == 0) {
it = v.erase(it); // 删除元素后更新迭代器
continue;
}
it++;
}
for (auto& val : v) {
cout << val << " "; // 1 3 5
}
}
补充:vector的erase函数,删除元素i后,返回元素i下一个元素的迭代器。
4. 迭代器遍历string容器
void test06() {
string str("i love china");
for (auto it = str.begin(); it != str.end(); it++) {
*it = *it - 32;
}
cout << str << endl; // ILOVECHINA
}