2017-11-28 8 views
0

WARC 파일을 구문 분석하기 위해 C++ 라이브러리를 작성 중이며 WARC 레코드 및 필드 데이터를 저장하는 클래스와 일부 입력 스트림에서 데이터를 읽는 연산자를 포함합니다. istream에서 읽고 WARCRecord 개체를 채우려면 operator>>이 있어야합니다. istream 스트림에서 읽을 수 있고 WARCRecord 개체로 구문 분석 할 수 있습니다. 그러나 입력 스트림에서 모든 WARC 레코드를 읽으려면 istream_iterator을 사용하고 싶습니다.istream_iterator 객체를 다시 사용합니까?

istream_iterator을 사용하여 스트림의 끝까지 반복 할 때 내 operator>>은 마지막 호출의 동일한 (copy?) 객체를받습니다. 이것은 예상되는 동작입니까, 아니면 클래스 정의에 연산자/생성자가 없습니다.

#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

그것은'표준 : istream_iterator '의 반복자가 T''의 새로운 객체마다 반복자는 증가를 생성할지 여부를 지정합니다. 따라서 구현은 매번 동일한 내부 객체를 다시 사용할 수 있으며, 참조가 해제되면 다시 반환 할 수 있습니다. – 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() 전에 전화 새로운 객체를 생성하지 않는 operator>>