2017-11-28 15 views
0

私はWARCファイルを解析するためのC++ライブラリを作成しています.WARCレコードとフィールドデータを格納するクラスと、入力ストリームからデータを読み取る演算子を含んでいます。 istreamから読み取り、WARCRecordオブジェクトに値を設定するには、operator>>があります。 istreamストリームから読み込み、WARCRecordオブジェクトに解析することができます。しかし、入力ストリームからすべてのWARCレコードを読み取るためにistream_iteratorを使用したいと思います。istream_iteratorはオブジェクトを再利用しますか?

istream_iteratorを使用してストリームの最後まで繰り返すと、私のoperator>>は最後の呼び出しの同じ(コピー?)オブジェクトを受け取ります。これは期待された動作ですか、私はクラス定義に演算子/コンストラクタがありませんか?

これは、この動作を確認するためのユニットテストを持つリポジトリのリンクである:このプログラムの出力は

#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 
上記テキストを実証するための簡単な例 https://github.com/jvanz/libwarc

MyClassオブジェクトのfieldsメンバサイズの累積に注意してください。

+0

を呼び出す前に、新しいオブジェクトを作成しません注意してください。したがって、実装は同じ内部オブジェクトを読み取りのたびに再利用し、逆参照すると返すことがあります – WhiZTiM

+0

ここにコードを貼り付けます。それが[mcve] –

答えて

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()それは `のstdのイテレータかどうかを指定されていないのです:: istream_iterator は`イテレータがインクリメントされるたびT ' `の新しいオブジェクトを作成します operator>>

関連する問題