浅谈STL中的输入流迭代器和输出流迭代器

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

using namespace std;

//直接从输入流中读取数据到输出流中,不经过中间层
//出了些问题,输入str1,不输出,然后输入str2,输出第一次输入的str1,不清楚为什么第一次输入后不输出任何东西。
int main()
{
ostream_iterator<string> out_iter(cout,"/n");
istream_iterator<string> in_iter(cin);
istream_iterator<string> eof;
while(in_iter!=eof)
*out_iter = *(in_iter++);

return 0;
}

输出:
abc //input1
bcd //input2
abc //output1
cde //input3
bcd //output2
def //input4
cde //output3
^Z //input5
def //output4
请按任意键继续. . .

输入str1,不输出,然后输入str2,输出第一次输入的str1,不清楚为什么第一次输入后不输出任何东西?

原帖地址:http://topic.csdn.net/u/20110428/14/21df0800-6471-4746-a403-d0224d69f81f.html

在Demon__Hunter的提示下,终于略懂一二,在此拿出来与大家分享。

 

在解释为什么会出现这样的问题之前,先要弄清楚在此过程中涉及的几个来自<iterator>的关键函数:

1,istream_iterator(istream_type& _Istr)
  : _Myistr(&_Istr)
  { // construct with input stream
  _Getval();
  }

2,void _Getval()
  { // get a _Ty value if possible
  if (_Myistr != 0 && !(*_Myistr >> _Myval))
   _Myistr = 0;
  }

3,_Myt operator++(int)
  { // postincrement
  _Myt _Tmp = *this;
  ++*this;
  return (_Tmp);
  }

4,_Myt& operator++()
  { // preincrement

 #if _HAS_ITERATOR_DEBUGGING
  if (_Myistr == 0)
   {
   _DEBUG_ERROR("istream_iterator is not incrementable");
   _SCL_SECURE_OUT_OF_RANGE;
   }
 #else
  _SCL_SECURE_VALIDATE_RANGE(_Myistr != 0);
 #endif /* _HAS_ITERATOR_DEBUGGING */

  _Getval();
  return (*this);
  }

5, ostream_iterator(ostream_type& _Ostr,
  const _Elem *_Delim = 0)
  : _Myostr(&_Ostr), _Mydelim(_Delim)
  { // construct from output stream and delimiter
  }

6,ostream_iterator<_Ty, _Elem, _Traits>& operator=(const _Ty& _Val)
  { // insert value into output stream, followed by delimiter
  *_Myostr << _Val;
  if (_Mydelim != 0)
   *_Myostr << _Mydelim;

 #if _HAS_ITERATOR_DEBUGGING
  if (!*_Myostr)
   {
   _DEBUG_ERROR("ostream_iterator is not dereferencable");
   _SCL_SECURE_OUT_OF_RANGE;
   }
 #else
  _SCL_SECURE_VALIDATE_RANGE(*_Myostr != NULL);
 #endif /* _HAS_ITERATOR_DEBUGGING */

  return (*this);
  }

首先:

ostream_iterator<string> out_iter(cout,"/n");
istream_iterator<string> in_iter(cin);
这两句是调用各自的构造函数,参见函数5与函数1。

再来分析一下函数1,函数1调用了函数2,函数2中的语句 *_Myistr >> _Myval 很明显需要输入一个字符串。从函数名上就可以很明显地看出来,getval()就是要输入一串字符串。这时我们输入了:abc,它被保存在in_iter对象中。

然后:

in_iter++

这条语句执行的是函数3,函数3又调用了函数4。函数4中同样有输入函数:getval()。现在我们输入:bcd。现在问题出来了,abc与bcd分别被保存在哪个对象中呢?现在的this指针指向的又是哪个对象呢?答案是明显的。this指针指向的具有值bcd的对象,在函数4中可以很明显地看出这一点来。那之前输入的abc保存在哪里呢?从函数3可以看出,它仍旧在原先的内存空间中,仍旧可以通过指针_Tmp来访问。暂且这么理解吧,现在我并不能很好解释这两个对象之间的关系,又或许这两个对象可能就是一个对象。

然后:

*(in_iter++)

这个就是简单地取字符串操作。将_Tmp对象中保存的字符串("abc")取出。

最后:

*out_iter = *(in_iter++);
调用函数6,将"abc"输出到屏幕中,并事先定义好的分隔符"/n"。

 

这整个过程就能很好地解释为什么会出现上面的输入了。

 

那该如何修正呢?

其实很简单,就是帖子二楼所说的:

{

*out_iter = *in_iter;
++in_iter;

}

这样就能完美地解决该问题了。

 

这和i++有什么不同呢?因为++运算符被重载了,所以产生了完全不同的效果。这下可以体会运算符重载是多么厉害的一个技术了吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值