C++ STL迭代器是访问容器元素的通用方式,分为输入、输出、前向、双向和随机访问五种类型,分别适用于不同场景;通过begin()和end()获取迭代器,可遍历vector、list、map等容器;使用时需注意插入或删除导致的迭代器失效问题,尤其在vector中易发生;可通过自定义迭代器类并重载*、++、==等操作符实现灵活访问;迭代器还与算法如copy、transform、find结合使用,提升代码复用性和效率。

C++ STL 迭代器是访问容器中元素的通用方式,它类似于指针,但提供了更高级的功能和安全性。理解迭代器的类型和用法是掌握 STL 的关键。
迭代器类型与用法详解:
迭代器是连接算法和容器的桥梁。它允许我们以统一的方式访问不同类型容器中的元素,而无需关心容器底层的实现细节。
C++ STL 提供了五种主要的迭代器类型,每种类型都具有不同的功能和限制。了解这些类型有助于我们选择最适合特定任务的迭代器。
立即学习“C++免费学习笔记(深入)”;
输入迭代器 (Input Iterator): 只读迭代器,只能单向移动,用于从容器中读取数据。只能读取一次,不能多次读取相同位置的值。例如,
istream_iterator
输出迭代器 (Output Iterator): 只写迭代器,只能单向移动,用于向容器中写入数据。只能写入一次,不能多次写入相同位置的值。例如,
ostream_iterator
前向迭代器 (Forward Iterator): 读写迭代器,可以单向移动,可以多次读取和写入相同位置的值。它具有输入迭代器和输出迭代器的所有功能。
双向迭代器 (Bidirectional Iterator): 读写迭代器,可以双向移动,可以多次读取和写入相同位置的值。它具有前向迭代器的所有功能,并增加了向后移动的能力。
list
set
multiset
map
multimap
随机访问迭代器 (Random Access Iterator): 读写迭代器,可以随机访问容器中的任何元素,可以进行加减运算,比较大小等操作。它具有双向迭代器的所有功能,并增加了随机访问的能力。
vector
deque
array
使用迭代器遍历容器是 STL 中常见的操作。以下是一些示例,展示了如何使用不同类型的迭代器遍历不同类型的容器。
示例 1: 使用迭代器遍历 vector
#include <iostream>
#include <vector>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用迭代器遍历 vector
for (std::vector<int>::iterator it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用 const_iterator 遍历 vector (只读)
for (std::vector<int>::const_iterator it = vec.cbegin(); it != vec.cend(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用 auto 关键字简化迭代器声明 (C++11 及以上)
for (auto it = vec.begin(); it != vec.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
// 使用范围 for 循环 (C++11 及以上)
for (int element : vec) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}示例 2: 使用迭代器遍历 list
#include <iostream>
#include <list>
int main() {
std::list<int> lst = {1, 2, 3, 4, 5};
// 使用迭代器遍历 list
for (std::list<int>::iterator it = lst.begin(); it != lst.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}示例 3: 使用迭代器遍历 map
#include <iostream>
#include <map>
int main() {
std::map<std::string, int> myMap = {{"apple", 1}, {"banana", 2}, {"cherry", 3}};
// 使用迭代器遍历 map
for (std::map<std::string, int>::iterator it = myMap.begin(); it != myMap.end(); ++it) {
std::cout << it->first << ": " << it->second << " ";
}
std::cout << std::endl;
return 0;
}迭代器失效是指迭代器指向的元素不再有效或不存在。这通常发生在容器修改后,例如插入、删除元素等。避免迭代器失效是编写健壮的 STL 代码的关键。
常见导致迭代器失效的操作:
vector
deque
vector
list
map
set
避免迭代器失效的策略:
尽量使用返回值: 某些容器操作(例如
erase
std::vector<int> vec = {1, 2, 3, 4, 5};
for (auto it = vec.begin(); it != vec.end(); ) {
if (*it % 2 == 0) {
it = vec.erase(it); // erase 返回指向下一个元素的迭代器
} else {
++it;
}
}避免在循环中修改容器大小: 如果需要在循环中修改容器大小,可以考虑使用
list
map/set
使用范围 for 循环 (C++11 及以上): 范围 for 循环在某些情况下可以避免迭代器失效的问题,但需要注意,如果在循环体内修改容器大小,仍然可能导致未定义行为。
小心使用 insert
erase
vector
deque
insert
erase
理解迭代器失效的原因和避免方法,可以帮助我们编写更可靠和高效的 STL 代码。
虽然 STL 提供了丰富的迭代器类型,但在某些情况下,我们可能需要自定义迭代器来满足特定的需求。自定义迭代器需要实现特定的接口和行为。
自定义迭代器的步骤:
定义迭代器类: 创建一个类,用于表示自定义迭代器。
定义迭代器类型别名: 在类中定义一些类型别名,例如
iterator_category
value_type
difference_type
pointer
reference
实现迭代器操作符: 重载迭代器需要支持的操作符,例如
*
++
==
!=
实现 begin()
end()
begin()
end()
示例:自定义一个简单的数组迭代器
#include <iostream>
template <typename T>
class ArrayIterator {
public:
using iterator_category = std::random_access_iterator_tag;
using value_type = T;
using difference_type = std::ptrdiff_t;
using pointer = T*;
using reference = T&;
ArrayIterator(T* ptr) : m_ptr(ptr) {}
reference operator*() const { return *m_ptr; }
pointer operator->() const { return m_ptr; }
ArrayIterator& operator++() {
++m_ptr;
return *this;
}
ArrayIterator operator++(int) {
ArrayIterator temp = *this;
++m_ptr;
return temp;
}
ArrayIterator& operator--() {
--m_ptr;
return *this;
}
ArrayIterator operator--(int) {
ArrayIterator temp = *this;
--m_ptr;
return temp;
}
ArrayIterator operator+(difference_type n) const { return ArrayIterator(m_ptr + n); }
ArrayIterator operator-(difference_type n) const { return ArrayIterator(m_ptr - n); }
difference_type operator-(const ArrayIterator& other) const { return m_ptr - other.m_ptr; }
bool operator==(const ArrayIterator& other) const { return m_ptr == other.m_ptr; }
bool operator!=(const ArrayIterator& other) const { return m_ptr != other.m_ptr; }
bool operator<(const ArrayIterator& other) const { return m_ptr < other.m_ptr; }
bool operator>(const ArrayIterator& other) const { return m_ptr > other.m_ptr; }
bool operator<=(const ArrayIterator& other) const { return m_ptr <= other.m_ptr; }
bool operator>=(const ArrayIterator& other) const { return m_ptr >= other.m_ptr; }
private:
T* m_ptr;
};
template <typename T, size_t N>
class MyArray {
public:
using iterator = ArrayIterator<T>;
MyArray() {}
iterator begin() { return iterator(m_data); }
iterator end() { return iterator(m_data + N); }
T& operator[](size_t index) { return m_data[index]; }
const T& operator[](size_t index) const { return m_data[index]; }
private:
T m_data[N];
};
int main() {
MyArray<int, 5> arr;
arr[0] = 1;
arr[1] = 2;
arr[2] = 3;
arr[3] = 4;
arr[4] = 5;
for (auto it = arr.begin(); it != arr.end(); ++it) {
std::cout << *it << " ";
}
std::cout << std::endl;
return 0;
}这个示例展示了如何自定义一个简单的数组迭代器,并将其用于遍历自定义的数组类。自定义迭代器可以让我们更灵活地控制数据的访问方式,并与其他 STL 算法进行集成。
STL 算法通常使用迭代器作为输入,对容器中的元素进行操作。理解如何使用迭代器进行算法操作是掌握 STL 的关键。
示例:使用 std::copy
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination(source.size());
// 使用 std::copy 算法复制 source 到 destination
std::copy(source.begin(), source.end(), destination.begin());
// 打印 destination 中的元素
for (int element : destination) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}示例:使用 std::transform
#include <iostream>
#include <vector>
#include <algorithm>
#include <functional>
int main() {
std::vector<int> source = {1, 2, 3, 4, 5};
std::vector<int> destination(source.size());
// 使用 std::transform 算法将 source 中的元素乘以 2 并存储到 destination
std::transform(source.begin(), source.end(), destination.begin(), [](int x) { return x * 2; });
// 打印 destination 中的元素
for (int element : destination) {
std::cout << element << " ";
}
std::cout << std::endl;
return 0;
}示例:使用 std::find
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
std::vector<int> vec = {1, 2, 3, 4, 5};
// 使用 std::find 算法查找元素 3
auto it = std::find(vec.begin(), vec.end(), 3);
if (it != vec.end()) {
std::cout << "Found element: " << *it << std::endl;
} else {
std::cout << "Element not found" << std::endl;
}
return 0;
}这些示例展示了如何使用迭代器与 STL 算法结合,对容器中的元素进行各种操作。掌握这些技巧可以让我们更高效地使用 STL。
以上就是C++STL迭代器类型与用法详解的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号