istream_iterator是否重用对象?

时间:2017-11-28 15:25:33

标签: c++ c++14 istream istream-iterator

我正在编写一个C ++库来解析WARC文件,它包含用于存储WARC记录和字段数据的类以及用于从某些输入流中读取数据的运算符。它有operator>>istream读取并填充WARCRecord对象。我能够从istream流中读取并将其解析为WARCRecord对象。但是,我想使用istream_iterator来读取输入流中的所有WARC记录。

当我使用istream_iterator进行迭代直到流结束时,operator>>接收到最后一次调用的相同(复制?)对象。这是预期的行为还是我在我的类定义中缺少一些运算符/构造函数?

这是带有单元测试的存储库链接,用于检查此行为:https://github.com/jvanz/libwarc

演示上述文字的简单示例:

#include <iostream>          
#include <istream>           
#include <sstream>           
#include <vector>            
#include <iterator>          


class MyClass                
{                            
        public:              
                std::vector<unsigned int> fields;          
        friend std::istream& operator>> (std::istream& is, MyClass& obj);                                              

}; 



std::istream& operator>> (std::istream& is, MyClass& obj){ 
        std::istream::sentry s(is);                        
        if (s) {             
                for (unsigned i = 0; i < 3; i++) {         
                        unsigned f;                        
                        is >> f;                           
                        obj.fields.push_back(f);           
                }            
        }                    
        return is;           
}                            

int main(void)               
{                            
        std::stringstream ss;                              
        ss << 1 << " " << 2 << " " << 3 << "  " << 4 << " " << 5 << " " << 6;                                          
        std::istream_iterator<MyClass> it(ss);             
        std::cout << it->fields.size() << std::endl;       
        it++;                
        std::cout << it->fields.size() << std::endl;       
        return 0;            
}

该程序的输出是:

$ ./a.out 
3
6

注意fields对象的MyClass成员大小的累积

1 个答案:

答案 0 :(得分:0)

我检查了我的计算机上的/usr/include/c++/7/bits/stream_operator.h以查看istream_iterator课程。事实上,据我所知,该类重用了同一个对象。

 /// Provides input iterator semantics for streams.                                                                                                                                                                                          
  template<typename _Tp, typename _CharT = char,                                                                                                                                                                                              
           typename _Traits = char_traits<_CharT>, typename _Dist = ptrdiff_t>                                                                                                                                                                
    class istream_iterator                                                                                                                                                                                                                    
    : public iterator<input_iterator_tag, _Tp, _Dist, const _Tp*, const _Tp&>                                                                                                                                                                 
    {                                                                                                                                                                                                                                         
    public:                                                                                                                                                                                                                                   
      typedef _CharT                         char_type;                                                                                                                                                                                       
      typedef _Traits                        traits_type;                                                                                                                                                                                     
      typedef basic_istream<_CharT, _Traits> istream_type;                                                                                                                                                                                    

    private:                                                                                                                                                                                                                                  
      istream_type*     _M_stream;                                                                                                                                                                                                            
      _Tp               _M_value;                                                                                                                                                                                                             
      bool              _M_ok;                                                                                                                                                                                                                

    public:                                                                                                                                                                                                                                   
      ///  Construct end of input stream iterator.                                                                                                                                                                                            
      _GLIBCXX_CONSTEXPR istream_iterator()                                                                                                                                                                                                   
      : _M_stream(0), _M_value(), _M_ok(false) {}                                                                                                                                                                                             

      ///  Construct start of input stream iterator.                                                                                                                                                                                          
      istream_iterator(istream_type& __s)                                                                                                                                                                                                     
      : _M_stream(std::__addressof(__s))                                                                                                                                                                                                      
      { _M_read(); }                                                                                                                                                                                                                          

      istream_iterator(const istream_iterator& __obj)                                                                                                                                                                                         
      : _M_stream(__obj._M_stream), _M_value(__obj._M_value),                                                                                                                                                                                 
        _M_ok(__obj._M_ok)                                                                                                                                                                                                                    
      { }                                                                                                                                                                                                                                     

      const _Tp&                                                                                                                                                                                                                              
      operator*() const                                                                                                                                                                                                                       
      {                                                                                                                                                                                                                                       
        __glibcxx_requires_cond(_M_ok,                                                                                                                                                                                                        
                                _M_message(__gnu_debug::__msg_deref_istream)                                                                                                                                                                  
                                ._M_iterator(*this));                                                                                                                                                                                         
        return _M_value;                                                                                                                                                                                                                      
      }                                                                                                                                                                                                                                       

      const _Tp*                                                                                                                                                                                                                              
      operator->() const { return std::__addressof((operator*())); }                                                                                                                                                                          

      istream_iterator&                                                                                                                                                                                                                       
      operator++()                                                                                                                                                                                                                            
      {                                                                                                                                                                                                                                       
        __glibcxx_requires_cond(_M_ok,                                                                                                                                                                                                        
                                _M_message(__gnu_debug::__msg_inc_istream)                                                                                                                                                                    
                                ._M_iterator(*this));                                                                                                                                                                                         
        _M_read();                                                                                                                                                                                                                            
        return *this;                                                                                                                                                                                                                         
      } 

 istream_iterator                                                                                                                                                                                                                        
      operator++(int)                                                                                                                                                                                                                         
      {                                                                                                                                                                                                                                       
        __glibcxx_requires_cond(_M_ok,                                                                                                                                                                                                        
                                _M_message(__gnu_debug::__msg_inc_istream)                                                                                                                                                                    
                                ._M_iterator(*this));                                                                                                                                                                                         
        istream_iterator __tmp = *this;                                                                                                                                                                                                       
        _M_read();                                                                                                                                                                                                                            
        return __tmp;                                                                                                                                                                                                                         
      }                                                                                                                                                                                                                                       

      bool                                                                                                                                                                                                                                    
      _M_equal(const istream_iterator& __x) const                                                                                                                                                                                             
      { return (_M_ok == __x._M_ok) && (!_M_ok || _M_stream == __x._M_stream); }                                                                                                                                                              

    private:                                                                                                                                                                                                                                  
      void                                                                                                                                                                                                                                    
      _M_read()                                                                                                                                                                                                                               
      {                                                                                                                                                                                                                                       
        _M_ok = (_M_stream && *_M_stream) ? true : false;                                                                                                                                                                                     
        if (_M_ok)                                                                                                                                                                                                                            
          {                                                                                                                                                                                                                                   
            *_M_stream >> _M_value;                                                                                                                                                                                                           
            _M_ok = *_M_stream ? true : false;                                                                                                                                                                                                
          }                                                                                                                                                                                                                                   
      }                                                                                                                                                                                                                                       
    };               

请注意_M_read()在调用operator>>

之前不会创建新对象