跳转到内容

C++ 流迭代器

来自代码酷

模板:Note

C++流迭代器[编辑 | 编辑源代码]

流迭代器(Stream Iterators)是C++标准模板库(STL)中一类特殊的迭代器适配器,用于将输入/输出流当作序列容器来处理。它们允许开发者使用迭代器接口从流中读取数据或向流中写入数据,从而与STL算法无缝集成。

核心概念[编辑 | 编辑源代码]

流迭代器分为两种主要类型:

  • istream_iterator:输入流迭代器,用于从输入流(如cin或文件流)读取数据
  • ostream_iterator:输出流迭代器,用于向输出流(如cout或文件流)写入数据

流迭代器的典型特征包括:

  • 单向迭代(只能前进)
  • 不提供随机访问能力
  • 输入迭代器只能读取,输出迭代器只能写入

输入流迭代器(istream_iterator)[编辑 | 编辑源代码]

输入流迭代器从输入流中提取数据,其模板声明为:

template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator;

基本用法示例[编辑 | 编辑源代码]

#include <iostream>
#include <iterator>
#include <vector>

int main() {
    // 从标准输入读取整数,直到遇到非整数或EOF
    std::istream_iterator<int> input_it(std::cin);
    std::istream_iterator<int> eof; // 默认构造表示流结束
    
    std::vector<int> numbers;
    
    // 使用流迭代器填充vector
    while (input_it != eof) {
        numbers.push_back(*input_it++);
    }
    
    // 输出读取的内容
    std::cout << "Read " << numbers.size() << " numbers:\n";
    for (int num : numbers) {
        std::cout << num << " ";
    }
    return 0;
}

输入示例

10 20 30 40 x

输出示例

Read 4 numbers:
10 20 30 40 

工作原理[编辑 | 编辑源代码]

  • 当创建istream_iterator时,它会立即尝试从流中读取第一个值
  • 每次解引用(*)操作返回当前缓存的值
  • 递增(++)操作会读取下一个值
  • 默认构造的迭代器作为流结束标记

输出流迭代器(ostream_iterator)[编辑 | 编辑源代码]

输出流迭代器向输出流中插入数据,其模板声明为:

template <class T, class charT = char, class traits = char_traits<charT>>
class ostream_iterator;

基本用法示例[编辑 | 编辑源代码]

#include <iostream>
#include <iterator>
#include <vector>

int main() {
    std::vector<int> vec = {1, 2, 3, 4, 5};
    
    // 创建输出流迭代器,指定cout为输出流,分隔符为", "
    std::ostream_iterator<int> output_it(std::cout, ", ");
    
    // 使用流迭代器输出vector内容
    for (int num : vec) {
        *output_it++ = num; // 等价于 std::cout << num << ", ";
    }
    
    std::cout << "\n";
    return 0;
}

输出示例

1, 2, 3, 4, 5, 

工作原理[编辑 | 编辑源代码]

  • 赋值操作(=)会将值写入输出流
  • 递增操作(++)不做实际工作,仅为保持接口一致性
  • 可以指定可选的分隔符字符串,在每次写入后输出

流迭代器与STL算法结合[编辑 | 编辑源代码]

流迭代器的真正威力在于与STL算法的结合使用:

文件复制示例[编辑 | 编辑源代码]

#include <fstream>
#include <iterator>
#include <algorithm>

int main() {
    std::ifstream input_file("input.txt");
    std::ofstream output_file("output.txt");
    
    // 使用流迭代器复制文件内容
    std::istream_iterator<char> input_it(input_file);
    std::istream_iterator<char> eof;
    std::ostream_iterator<char> output_it(output_file);
    
    std::copy(input_it, eof, output_it);
    
    return 0;
}

数值处理管道[编辑 | 编辑源代码]

#include <iostream>
#include <iterator>
#include <vector>
#include <algorithm>
#include <numeric>

int main() {
    // 从标准输入读取双精度数
    std::istream_iterator<double> input_it(std::cin);
    std::istream_iterator<double> eof;
    
    // 计算输入数值的平均值
    double sum = std::accumulate(input_it, eof, 0.0);
    int count = std::distance(input_it, eof);
    
    std::cout << "Average: " << (sum / count) << "\n";
    
    return 0;
}

高级应用[编辑 | 编辑源代码]

自定义类型的流迭代[编辑 | 编辑源代码]

要使自定义类型支持流迭代器,需要重载<<>>运算符:

#include <iostream>
#include <iterator>
#include <vector>

struct Point {
    double x, y;
    
    friend std::istream& operator>>(std::istream& is, Point& p) {
        return is >> p.x >> p.y;
    }
    
    friend std::ostream& operator<<(std::ostream& os, const Point& p) {
        return os << "(" << p.x << ", " << p.y << ")";
    }
};

int main() {
    std::vector<Point> points;
    
    // 从标准输入读取点
    std::copy(std::istream_iterator<Point>(std::cin),
              std::istream_iterator<Point>(),
              std::back_inserter(points));
    
    // 输出所有点
    std::copy(points.begin(), points.end(),
              std::ostream_iterator<Point>(std::cout, "\n"));
    
    return 0;
}

输入示例

1.0 2.0
3.5 4.2

输出示例

(1.0, 2.0)
(3.5, 4.2)

性能考虑[编辑 | 编辑源代码]

  • 流迭代器通常比直接流操作稍慢,因为增加了抽象层
  • 对于大量数据,考虑使用缓冲区或直接流操作
  • 在性能关键代码中应进行基准测试

常见错误与陷阱[编辑 | 编辑源代码]

1. 悬空迭代器:流被销毁后继续使用关联的流迭代器 2. 状态检查:忘记检查流状态可能导致无限循环 3. 类型不匹配:流数据类型与迭代器模板参数不匹配 4. 多次解引用:输入流迭代器每次解引用都会导致值被读取

总结表[编辑 | 编辑源代码]

特性 istream_iterator ostream_iterator
方向 输入 输出
可解引用 否(但可赋值)
可递增 是(无实际效果)
结束标记 默认构造的迭代器
典型用途 从流读取数据 向流写入数据

进一步学习[编辑 | 编辑源代码]

  • 结合std::copy和其他STL算法使用流迭代器
  • 探索istreambuf_iteratorostreambuf_iterator处理原始字符流
  • 研究如何将流迭代器与并行算法结合使用(C++17及以上)

模板:Tip