全面掌握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;
}