C++ STL 迭代器使用指南

全面掌握C++标准模板库中的迭代器概念、类型和使用方法

STL迭代器概览

迭代器是STL的核心概念,提供了一种访问容器元素的通用方法,使算法能够独立于容器类型工作。

迭代器的基本概念

迭代器类别
5种

输入、输出、前向、双向、随机访问

核心操作
6种

解引用、递增、递减、比较等

关键特性
通用性

算法与容器解耦

迭代器基本使用
#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;
}
前向迭代器
读写
单向

可读写元素并向前移动,支持多次遍历。

支持操作极div>
读写、递增
典型容器
forward_list
访问方向
仅向前
前向迭代器示例
#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;
}
双向迭代器
读写
双向

可读写元素并向前或向后移动,支持多次遍历。

支持操作
读写、递增、递减
典型容器
list, set, map
访问方向
双向
双向迭代器示例
#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;
}
随机访问迭代器
读写
随机访问

功能最强大的迭代器,支持所有指针运算操作,包括随机访问。

支持操作
读写、随机访问
典型容器
vector, deque, array
访问能力
任意位置直接访问
随机访问迭代器示例
#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;
}

迭代器使用技巧

迭代器适配器

迭代器适配器提供特殊功能的迭代器,用于扩展迭代器的能力。

反向迭代器
反向遍历

允许反向遍历容器的适配器,适用于双向迭代器和随机访问迭代器。

支持容器
vector, deque, list等
创建方法
rbegin(), rend()
主要用途
反向遍历
反向迭代器示例
#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。

适配器类型
3种
主要用途
算法结果插入容器
常用算法
copy, transform
插入迭代器示例
#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。

输入流迭代器
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;
}
移动迭代器
移动语义

将解引用操作转换为右值引用的迭代器适配器,用于实现移动语义。

创建方法
make_move_iterator
主要用途
转移资源所有权
使用场景
大数据转移
移动迭代器示例
#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)

使用iterator_traits获取迭代器的属性信息。

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;
}