全面掌握C++标准模板库中的迭代器概念、类型和使用方法
迭代器是STL的核心概念,提供了一种访问容器元素的通用方法,使算法能够独立于容器类型工作。
输入、输出、前向、双向、随机访问
解引用、递增、递减、比较等
算法与容器解耦
#include <iostream> #include <vector> #include <list> int main() { // vector迭代器示例 std::vector<int> vec = {1, 2, 3, 4, 5}; std::cout << "Vector: "; for (auto it = vec.begin(); it != vec.end(); ++it) { std::cout << *it << " "; } // list迭代器示例 std::list<std::string> names = {"Alice", "Bob", "Charlie"}; std::cout << "\nNames: "; for (auto it = names.begin(); it != names.end(); ++it) { std::cout << *it << " "; } // 修改元素 auto vec_it = vec.begin(); *vec_it = 10; // 修改第一个元素 // 迭代器运算 std::advance(vec_it, 3); // 前进3个位置 std::cout << "\nFourth element: " << *vec_it; return 0; }
STL定义了5种迭代器类别,每种提供不同级别的功能和访问能力。
只能读取元素并向前移动的迭代器,适用于单次遍历。
#include <iostream> #include <iterator> int main() { std::istream_iterator<int> input_it(std::cin); std::istream_iterator<int> end_it; std::cout << "Enter integers (Ctrl+D to end): "; while (input_it != end_it) { std::cout << "Read: " << *input_it << "\n"; ++input_it; } return 0; }
只能写入元素并向前移动的迭代器,适用于单次输出。
#include <iostream> #include <iterator> #include <vector> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; std::ostream_iterator<int> output_it(std::cout, " "); std::cout << "Vector content: "; std::copy(vec.begin(), vec.end(), output_it); return 0; }
可读写元素并向前移动,支持多次遍历。
#include <iostream> #include <forward_list> int main() { std::forward_list<int> flist = {10, 20, 30, 40}; // 遍历前向链表 std::cout << "Forward list: "; for (auto it = flist.begin(); it != flist.end(); ++it) { std::cout << *it << " "; } // 修改元素 auto it = flist.begin(); *it = 100; // 只能向前移动 ++it; // 正确 // --it; // 错误!前向迭代器不支持递减 return 0; }
可读写元素并向前或向后移动,支持多次遍历。
#include <iostream> #include <list> int main() { std::list<int> lst = {1, 2, 3, 4, 5}; // 向前遍历 std::cout << "Forward: "; for (auto it = lst.begin(); it != lst.end(); ++it) { std::cout << *it << " "; } // 向后遍历 std::cout << "\nBackward: "; for (auto it = lst.rbegin(); it != lst.rend(); ++it) { std::cout << *it << " "; } // 双向移动 auto it = lst.begin(); ++it; // 前进 --it; // 后退 return 0; }
功能最强大的迭代器,支持所有指针运算操作,包括随机访问。
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {10, 20, 30, 40, 50}; // 直接访问任意位置 std::cout << "Third element: " << vec[2] << "\n"; std::cout << "First element: " << *vec.begin() << "\n"; // 迭代器运算 auto it1 = vec.begin(); auto it2 = it1 + 3; // 直接前进3个位置 std::cout << "Distance: " << it2 - it1 << "\n"; // 比较操作 if (it1 < it2) { std::cout << "it1 comes before it2\n"; } // 使用算法 std::sort(vec.begin(), vec.end()); // 二分查找 if (std::binary_search(vec.begin(), vec.end(), 30)) { std::cout << "30 found in vector\n"; } // 修改元素 it1[1] = 100; // 修改第二个元素 std::cout << "Modified vector: "; for (int n : vec) std::cout << n << " "; return 0; }
迭代器类别形成一个层次结构,每个更高级别的迭代器继承低级迭代器的所有功能:
操作 | 输入 | 输出 | 前向 | 双向 | 随机访问 |
---|---|---|---|---|---|
读取 (*it) | ✓ | ✗ | ✓ | ✓ | ✓ |
写入 (*it = ...) | ✗ | ✓ | ✓ | ✓ | ✓ |
递增 (++) | ✓ | ✓ | ✓ | ✓ | ✓ |
递减 (--) | ✗ | ✗ | ✗ | ✓ | ✓ |
比较 (==, !=) | ✓ | ✓ | ✓ | ✓极td> | ✓ |
随机访问 (it + n) | ✗ | ✗ | ✗ | ✗ | ✓ |
下标访问 (it[n]) | ✗ | ✗ | ✗ | ✗ | ✓ |
关系比较 (<, >, etc) | ✗ | ✗ | ✗ | ✗ | ✓ |
掌握迭代器的核心操作和常见用法,提高C++编程效率。
使用迭代器遍历各种容器中的元素。
#include <iostream> #include <vector> #include <list> #include <map> int main() { // 1. 遍历vector std::vector<int> numbers = {1, 2, 3, 4, 5}; std::cout << "Vector elements: "; for (auto it = numbers.begin(); it != numbers.end(); ++it) { std::cout << *it << " "; } // 2. 遍历list std::list<std::string> fruits = {"Apple", "Banana", "Cherry"}; std::cout << "\nList elements: "; for (auto it = fruits.begin(); it != fruits.end(); ++it) { std::cout << *it << " "; } // 3. 遍历map std::map<int, std::string> students = { {101, "Alice"}, {102, "Bob"}, {103, "Charlie"} }; std::cout << "\nMap elements:\n"; for (auto it = students.begin(); it != students.end(); ++it) { std::cout << "ID: " << it->first << ", Name: " << it->second << "\n"; } // 4. 使用const迭代器 std::cout << "\nConst iteration: "; for (auto cit = numbers.cbegin(); cit != numbers.cend(); ++cit) { // *cit = 10; // 错误,不能修改常量值 std::cout << *cit << " "; } // 5. 使用reverse迭代器 std::cout << "\nReverse iteration: "; for (auto rit = numbers.rbegin(); rit != numbers.rend(); ++rit) { std::cout << *rit << " "; } return 0; }
使用迭代器修改容器中的元素值。
#include <iostream> #include <vector> #include <list> int main() { std::vector<int> numbers = {1, 2, 3, 4, 5}; // 使用迭代器修改元素 for (auto it = numbers.begin(); it != numbers.end(); ++it) { *it *= 2; // 每个元素乘以2 } std::cout << "Modified vector: "; for (int n : numbers) std::cout << n << " "; // 在list中修改元素 std::list<std::string> words = {"apple", "banana", "cherry"}; auto word_it = words.begin(); std::advance(word_it, 1); *word_it = "blueberry"; std::cout << "\nModified list: "; for (const auto& word : words) std::cout << word << " "; // 修改map中的值 std::map<int, std::string> students = { {101, "Alice"}, {102, "Bob"}, {103, "Charlie"} }; auto it = students.find(102); if (it != students.end()) { it->second = "Robert"; // 修改值 } std::cout << "\nStudents: "; for (const auto& s : students) { std::cout << "[" << s.first << ": " << s.second << "] "; } return 0; }
了解在容器修改时迭代器失效的情况。
#include <iostream> #include <vector> #include <list> int main() { // vector迭代器失效示例 std::vector<int> vec = {1, 2, 3, 4, 5}; auto vec_it = vec.begin() + 2; std::cout << "Third element: " << *vec_it << "\n"; // 添加元素导致vector重新分配内存 vec.push_back(6); // 此时vec_it可能失效! // std::cout << *vec_it << "\n"; // 未定义行为 // 安全做法:重新获取迭代器 vec_it = vec.begin() + 2; std::cout << "New third element: " << *vec_it << "\n"; // list迭代器失效示例 std::list<int> lst = {10, 20, 30, 40}; auto lst_it = lst.begin(); std::advance(lst_it, 2); // 指向30 // 删除元素 lst.erase(lst_it); // 删除30,lst_it失效 // 安全做法:erase返回下一个有效迭代器 lst_it = lst.begin(); std::advance(lst_it, 1); lst_it = lst.erase(lst_it); // 删除20,返回指向30的迭代器 std::cout << "List after erasure: "; for (int n : lst) std::cout << n << " "; return 0; }
结合STL算法使用迭代器。
#include <iostream> #include <vector> #include <algorithm> #include <iterator> int main() { std::vector<int> data = {5, 3, 1, 4, 2}; // 1. 排序 std::sort(data.begin(), data.end()); // 2. 查找元素 auto it = std::find(data.begin(), data.end(), 3); if (it != data.end()) { std::cout << "Found 3 at position: " << std::distance(data.begin(), it) << "\n"; } // 3. 复制元素 std::vector<int> copy; std::copy(data.begin(), data.end(), std::back_inserter(copy)); // 4. 转换元素 std::vector<int> squares; std::transform(data.begin(), data.end(), std::back_inserter(squares), [](int x) { return x * x; }); // 5. 累加 int sum = std::accumulate(data.begin(), data.end(), 0); std::cout << "Sum: " << sum << "\n"; // 6. 输出到控制台 std::cout << "Squares: "; std::copy(squares.begin(), squares.end(), std::ostream_iterator<int>(std::cout, " ")); return 0; }
迭代器适配器提供特殊功能的迭代器,用于扩展迭代器的能力。
允许反向遍历容器的适配器,适用于双向迭代器和随机访问迭代器。
#include <iostream> #include <vector> #include <algorithm> int main() { std::vector<int> vec = {1, 2, 3, 4, 5}; // 反向遍历 std::cout << "Reverse: "; for (auto rit = vec.rbegin(); rit != vec.rend(); ++rit) { std::cout << *rit << " "; } // 使用算法反向查找 auto rit = std::find(vec.rbegin(), vec.rend(), 3); if (rit != vec.rend()) { std::cout << "\nFound 3 at position: " << std::distance(vec.begin(), rit.base() - 1); } // 反向排序 std::sort(vec.rbegin(), vec.rend()); std::cout << "\nReverse sorted: "; for (int n : vec) std::cout << n << " "; return 0; }
将赋值操作转换为插入操作的迭代器适配器,包括back_inserter、front_inserter和inserter。
#include <iostream> #include <vector> #include <list> #include <iterator> #include <algorithm> int main() { std::vector<int> src = {1, 2, 3, 4, 5}; std::vector<int> dest; std::list<int> lst; // 使用back_inserter在末尾插入 std::copy(src.begin(), src.end(), std::back_inserter(dest)); std::cout << "dest: "; for (int n : dest) std::cout << n << " "; // 使用front_inserter在头部插入 std::copy(src.begin(), src.end(), std::front_inserter(lst)); std::cout << "\nlst: "; for (int n : lst) std::cout << n << " "; // 使用inserter在指定位置插入 std::vector<int> vec = {10, 20, 30}; auto it = vec.begin() + 1; std::copy(src.begin(), src.end(), std::inserter(vec, it)); std::cout << "\nvec: "; for (int n : vec) std::cout << n << " "; return 0; }
将流当作序列处理的迭代器适配器,包括istream_iterator和ostream_iterator。
#include <iostream> #include <iterator> #include <vector> #include <algorithm> #include <sstream> int main() { // 从标准输入读取整数 std::cout << "Enter integers (Ctrl+D to end): "; std::istream_iterator<int> input_it(std::cin); std::istream_iterator<int> end_it; std::vector<int> numbers; std::copy(input_it, end_it, std::back_inserter(numbers)); // 处理数据 std::transform(numbers.begin(), numbers.end(), numbers.begin(), [](int n) { return n * n; }); // 输出到标准输出 std::cout << "Squared values: "; std::ostream_iterator<int> output_it(std::cout, " "); std::copy(numbers.begin(), numbers.end(), output_it); // 使用字符串流 std::cout << "\n\nUsing string stream:\n"; std::string data = "1.5 2.5 3.5 4.5"; std::istringstream iss(data); std::istream_iterator<double> dbl_it(iss); std::istream_iterator<double> dbl_end; double sum = 0; while (dbl_it != dbl_end) { sum += *dbl_it; ++dbl_it; } std::cout << "Sum: " << sum; return 0; }
将解引用操作转换为右值引用的迭代器适配器,用于实现移动语义。
#include <iostream> #include <vector> #include <iterator> #include <algorithm> #include <string> int main() { std::vector<std::string> src; src.push_back("Hello"); src.push_back("World"); src.push_back("C++"); std::cout << "Source before move: "; for (const auto& s : src) std::cout << s << " "; // 使用移动迭代器转移资源 std::vector<std::string> dest; std::copy(std::make_move_iterator(src.begin()), std::make_move_iterator(src.end()), std::back_inserter(dest)); std::cout << "\nDestination: "; for (const auto& s : dest) std::cout << s << " "; std::cout << "\nSource after move: "; for (const auto& s : src) std::cout << s << " "; // 原始字符串被移动 return 0; }
探索迭代器的高级用法和技巧。
创建自定义容器或数据结构的迭代器。
#include <iostream> #include <iterator> // 简单的整数范围类 class IntRange { int start; int end; public: IntRange(int s, int e) : start(s), end(e) {} // 自定义迭代器 class Iterator { int current; public: using iterator_category = std::input_iterator_tag; using value_type = int; using difference_type = int; using pointer = int*; using reference = int&; Iterator(int c) : current(c) {} int operator*() const { return current; } Iterator& operator++() { ++current; return *this; } Iterator operator++(int) { Iterator tmp = *this; ++current; return tmp; } bool operator==(const Iterator& other) const { return current == other.current; } bool operator!=(const Iterator& other) const { return !(*this == other); } }; Iterator begin() const { return Iterator(start); } Iterator end() const { return Iterator(end + 1); } }; int main() { IntRange range(5, 10); std::cout << "Range: "; for (int n : range) { std::cout << n << " "; } // 使用STL算法 std::cout << "\nSum: " << std::accumulate(range.begin(), range.end(), 0); return 0; }
使用iterator_traits获取迭代器的属性信息。
#include <iostream> #include <iterator> #include <vector> #include <type_traits> #include <list> template <typename Iter> void print_iterator_type() { using traits = std::iterator_traits<Iter>; std::cout << "Iterator category: "; if (std::is_same_v<typename traits::iterator_category, std::random_access_iterator_tag>) { std::cout << "Random Access"; } else if (std::is_same_v<typename traits::iterator_category, std::bidirectional_iterator_tag>) { std::cout << "Bidirectional"; } else if (std::is_same_v<typename traits::iterator_category, std::forward_iterator_tag>) { std::cout << "Forward"; } else { std::cout << "Other"; } std::cout << "\nValue type: " << typeid(typename traits::value_type).name(); std::cout << "\nDifference type: " << typeid(typename traits::difference_type).name() << "\n\n"; } int main() { std::vector<int> vec; std::list<double> lst; std::cout << "Vector iterator traits:\n"; print_iterator_type<decltype(vec.begin())>(); std::cout << "List iterator traits:\n"; print_iterator_type<decltype(lst.begin())>(); return 0; }
了解不同算法对迭代器类别的要求。
算法 | 所需迭代器类别 | 时间复杂度 | 典型容器 |
---|---|---|---|
std::sort | 随机访问 | O(n log n) | vector, deque, array |
std::stable_sort | 随机访问 | O(n log n) | vector, deque, array |
std::list::sort | 双向 | O(n log n) | list |
std::advance | 输入/前向/双向/随机访问 | O(n)/O(1) | 所有 |
std::distance | 输入/前向/双向/随机访问 | O(n)/O(1) | 所有 |
std::binary_search | 前向或更强 | O(log n) | 有序容器 |
std::find | 输入 | O(n) | 所有极> |
std::reverse | 双向 | O(n) | vector, list, deque |
#include <iostream> #include <vector> #include <algorithm> #include <iterator> int main() { // 1. 尽量使用auto简化迭代器声明 std::vector<int> vec = {5, 3, 1, 4, 2}; auto it = std::find(vec.begin(), vec.end(), 3); // 2. 使用const迭代器防止意外修改 auto cit = vec.cbegin(); // *cit = 10; // 错误,不能修改 // 3. 使用算法代替手动循环 std::sort(vec.begin(), vec.end()); // 4. 使用迭代器适配器简化操作 std::vector<int> squares; std::transform(vec.begin(), vec.end(), std::back_inserter(squares), [](int x) { return x * x; }); // 5. 使用移动语义提高效率 std::vector<std::string> words = {"Hello", "World"}; std::vector<std::string> words_copy; std::move(words.begin(), words.end(), std::back_inserter(words_copy)); // 6. 避免迭代器失效 for (auto it = vec.begin(); it != vec.end(); ) { if (*it % 2 == 0) { it = vec.erase(it); // 正确使用erase返回值 } else { ++it; } } // 7. 使用标准算法函数 auto max_it = std::max_element(vec.begin(), vec.end()); if (max_it != vec.end()) { std::cout << "Max value: " << *max_it << "\n"; } // 8. 使用范围for循环简化代码 std::cout << "Final vec: "; for (int n : vec) { std::cout << n << " "; } return 0; }