STL源码分析ostream_iterator和istream_iterator

简介

istream_iterator和ostream_iterator是两个迭代器主要用来输入输出。istream_iterator允许使用懒惰求值,标准库不保证迭代器立即从流读取数据,具体实现中可以推迟从流中读取数据,直到我们使用迭代器时才真正读取,例如需要解引用时。ostream_iterator是write only的,所以不能有类似ostream_iter != pointer的操作。另外分隔符必须是字符串。必须将ostream_iterator绑定到一个指定的流,不允许空的或表示尾后位置的ostream_iterator。

ostream_iterator

下面是ostream_iterator的类模板源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
template <class T, class char T = char, class traits = char_traits<charT>>
class ostream_iterator : public iterator<output_iterator_tag, void, void, void, void>
{
basic_ostream<charT, traits> *out_stream;
const charT* delim;
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_ostream<charT, traits> ostream_type;
ostream_iterator(ostream_type &s) : out_stream(&s), delim(0) {}
ostream_iterator(ostream_type &s, const charT *delimiter) : out_stream(x.out_stream), delim(x.delim) {}
~ostream_iterator(){}
ostream_iterator<T, charT, traits> &operator=(const T &value)
{
*out_stream << value;
if (delim != 0) *out_stream << delim;
return *this;
}
ostream_iterator<T, charT, traits> &operator*() {return *this; }
ostream_iterator<T, charT, traits> &operator++() {return *this; }
ostream_iterator<T, charT, traits> &operator++(int) {return *this; }
}

从源代码中可以看到,outstream是一个basic_outstream指针,对于ostream_iterator(假设out为其对象),*out、out++、++out操作相同,都是返回的out。

下面是一个实际调用的例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
std::ostream_iterator<int> out_it(std::cout, ",");
std::copy(myvector.begin(), myvector.end(), out_it);
template <class InputIterator, class OutputIterator>
OutputIterator copy(InputIterator first, InputIterator last, OutputIterator result)
{
while (first != last)
{
*result = *first; // 相当于两条语句 cout << *first; cout << ",";
++result; ++first;
}
return result;
}

这里++result是没有作用的,因为每次赋值时就会提交写操作,不需要移动迭代器。

istream_iterator

对于istream_iterator的分析在下面源代码的注释中进行了部分解析。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
istream_iterator<double> eos; // end of stream iterator,调用构造函数1
istream_iterator<double> iit(cin); // 调用构造函数2,创建时已经发生了读取操作,value被赋值
if (iit != eos) value1 = *iit; // 把读取的值赋值给value1;
++iit; // 读取下一个值存到iit中。
if (iit != eos) value2 = *iit; // 把读取的值赋值给value2;
cout << value1 << "*" << value2 << "=" << value1 * value2 << endl;
template <class T, class charT = char, class traits = char_traits<charT>, class Distance = ptrdiff_t>
class istream_iterator : public iterator <input_iterator_tag, T, Distance, const T*, const T&>
{
basic_istream<chatT, traits> *in_stream;
T value;
public:
typedef charT char_type;
typedef traits traits_type;
typedef basic_istream<charT, traits> istream_type;
istream_iterator():in_stream(0) {} //构造函数1
istream_iterator(istream_type &s) : in_stream(&s) { ++*this; } //构造函数2,调用operator++()
istream_iterator(const istream iterator<T, charT, traits, Distance> &x) //构造函数3
: in_stream(x.in_stream), value(x.value);
const T& operator*() const {return value; }
const T* operator->() const {return &value; }
istream_iterator<T, chatT, traits, Distance> &operator++()
{
if (in_stream && !(*in_stream >> value)) in_stream = 0;
return *this;
}
istream_iterator<T, charT, traits, Distance> operator++(int)
{
istream_iterator<T, charT, traits, Distance> tmp = *this;
++*this;
return tmp;
}
}

声明

若有错误,欢迎讨论。严禁抄袭,仅用于学习。

坚持原创技术分享,您的money将鼓励我继续创作!