C++ 流迭代器
外观
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_iterator
和ostreambuf_iterator
处理原始字符流 - 研究如何将流迭代器与并行算法结合使用(C++17及以上)