설날에 강좌업뎃 합니다.. ^^
이번에는 STL 모든 Container에서 기본으로 사용하는 allocator<T> 에 대한 기본적인 활용 예에 대하여
간단히 설명하고, allocator<T> 와 함께 사용하는 uninitialized_fill, uninitialized_fill_n, uninitialized_copy,
uninitialized_copy _n 사용 방법도 같이 보도록 하겠습니다.
메모리 관련된 부분이라 모든 것을 설명하기는 어려우니 궁금하신 점은 덧글 바랍니다.
보통 array의 상수 정의를 대신하기 위해 new로 memory 할당하는 형태의 class를 만드는 경우가 많지만,
좀 더 generic 한 형태로 자신의 Container에 memory control을 위해 allocator class를 사용하면 많은
이점이 있습니다.
allocator class를 사용하기 위해서는 <memory>를 include 하여야 합니다.
참고 http://msdn2.microsoft.com/en-us/library/96xh3xxe(VS.71).aspx
http://www.sgi.com/tech/stl/table_of_contents.html (8. Memory allocation 을 참고하세요. )
아래의 예는 예전 강좌에서도 보여 드렸던 Standard library와 유사한 vector에서 push_back 기능을 제외한
Fixed vector입니다. 그리고 FixedVec을 이용한 실행 프로그램입니다.
FixedVec.hpp에서 주의 깊게 보아야 할 부분은 member function인 create()와 destroy() 입니다.
create는 세 가지로 overloading 되어 있습니다.
create()
아무것도 하지않으며, data와 avail을 NULL로 지정합니다.
create( size_type, const T & )
주어진 size 만큼 allocator의 member인 allocate를 이용하여 할당하고,
uninitialized_fill을 이용하여 T type의 value로 initialize 합니다.
create( const_iterator, const_iterator)
iterator을 이용하여 uninitialized_copy를 합니다.
이때 주의 사항(당연한 것이지만)은 첫 번째 인자가 두 번째 인자 보다 앞이여야 합니다.
uninitialized_fill = http://www.sgi.com/tech/stl/uninitialized_fill.html
http://msdn2.microsoft.com/en-us/library/a3txak8w(VS.71).aspx
uninitialized_fill_n = http://www.sgi.com/tech/stl/uninitialized_fill_n.html
http://msdn2.microsoft.com/en-us/library/k2302sd6(VS.71).aspx
uninitialized_copy = http://www.sgi.com/tech/stl/uninitialized_copy.html
http://msdn2.microsoft.com/en-us/library/ctht4stc(VS.71).aspx
uninitialized_copy_n = http://www.sgi.com/tech/stl/uninitialized_copy_n.html
모두 iterator(pointer)를 인자로 요구하며, allocator로 할당된 공간에 대하여 처리를 합니다.
그리고, 링크 사이트의 예를 보시면 아시겠지만, malloc 으로 할당된 공간도 동일하게 처리합니다.
memcpy와 유사한 역할을 한다고 보시면 되겠죠.
destroy()
할당된 부분의 모든 요소를 allocator의 member인 destroy로 제거(파괴) 하고 할당된 메모리
공간을 deallocate로 제거(파괴) 합니다.
allocator class는 별도의 operator를( [], -> ) 를 제공하지 않으며 ( operator ==, != 은 사용할 수 있습니다 )
iterator로 정의된 pointer의 operator로 접근하고 처리 할 수 있습니다.
FixedVec.hpp에 operator[] 정의를 참고 하세요.
FixedVec.hpp
1 #include <algorithm> 2 #include <cstddef> 3 #include <memory> 4 #include <stdexcept> 5 6 template < typename T > 7 class FixedVec{ 8 public: 9 typedef T* iterator; 10 typedef const T* const_iterator; 11 typedef T& reference; 12 typedef const T& const_reference; 13 typedef T value_type; 14 typedef size_t size_type; 15 16 FixedVec() { create(); } ///< default construct 17 explicit FixedVec( size_type n, const T& t = T() ) { create( n, t ); } ///< construct overloading 18 FixedVec( const FixedVec& fv ) { create( fv.begin(), fv.end() ); } ///< copy construct 19 virtual ~FixedVec() { destroy(); } ///< destruct 20 21 //! operator overloading 22 FixedVec& operator= ( const FixedVec& ); ///< assignment 23 value_type& operator[] ( size_type i ) { return data[i]; } ///< operator [] 24 const value_type& operator[] ( size_type i ) const { return data[i]; }///< const T operator[] 25 26 //! public method 27 size_type size () const { return avail - data; } ///< return value is to allocate size of FixedVec 28 iterator begin () { return data; } ///< data iterator 29 const_iterator begin () const { return data; } ///< data const_iterator 30 iterator end () { return avail; } ///< avail iterator 31 const_iterator end () const { return avail; } ///< avail const_iterator 32 33 void clear () { destroy(); } ///< same destroy 34 bool empty () const { return data == avail; } ///< empty 35 private: 36 iterator data; ///< first element in the FixedVec 37 iterator avail; ///< (one past) the last element in the FixedVec 38 std::allocator<T> alloc; ///< object to handle memory allocation 39 40 void create (); ///< memory allocation initialize 41 void create ( size_type, const T& ); ///< memory allocation by size and value 42 void create ( const_iterator, const_iterator ); ///< memory allocation by iterator 43 void Swap ( FixedVec& ); ///< container data swapping 44 void destroy (); ///< memory deallocation 45 }; 46 47 template < typename T > 48 FixedVec< T >& FixedVec< T >::operator= ( const FixedVec< T > &rhs ) 49 { 50 FixedVec< T > temp(rhs); 51 Swap( temp ); 52 return *this; 53 } 54 55 template < typename T > 56 void FixedVec< T >::create() 57 { 58 data = avail = 0; 59 } 60 61 template < typename T > 62 void FixedVec< T >::create(size_type n, const T& val) 63 { 64 data = alloc.allocate(n); 65 avail = data + n; 66 std::uninitialized_fill(data, avail, val); 67 } 68 69 template < typename T > 70 void FixedVec< T >::create(const_iterator i, const_iterator j) 71 { 72 data = alloc.allocate(j - i); 73 avail = std::uninitialized_copy(i, j, data); 74 } 75 76 template < typename T > 77 void FixedVec< T >::destroy() 78 { 79 if (data) { 80 iterator it = avail; 81 while (it != data) 82 alloc.destroy(--it); 83 alloc.deallocate(data, avail - data); 84 } 85 86 data = avail = 0; 87 } 88 89 template < typename T > 90 void FixedVec< T >::Swap ( FixedVec< T > &rhs ) 91 { 92 std::swap( alloc, rhs.alloc ); 93 std::swap( data , rhs.data ); 94 std::swap( avail, rhs.avail ); 95 } |
main.cpp
1 #include <iostream> 2 #include <algorithm> 3 #include <string> 4 #include <iterator> 5 #include <stdexcept> 6 7 #include "FixedVec.hpp" 8 9 template< typename T > 10 void PrintContainerElement( const T& t, const std::string title = "Container" ) 11 { 12 typedef typename T::value_type type; 13 std::cout << title << " : "; 14 std::copy( t.begin(), t.end(), std::ostream_iterator< type >( std::cout, " " ) ); 15 std::cout << std::endl; 16 } 17 18 int main() 19 { 20 try{ 21 FixedVec< std::string > fvecStrA; 22 FixedVec< std::string > fvecStrB( 15, "B" ); 23 FixedVec< std::string > fvecStrC( 20, "C" ); 24 25 if( fvecStrA.empty() ){ 26 std::cout << "fvecStrA was empty" << std::endl; 27 } 28 29 PrintContainerElement( fvecStrA, "Fixed Vector A" ); 30 31 FixedVec< std::string >::size_type sz = 10; 32 fvecStrA = FixedVec< std::string >( sz, "A" ); 33 PrintContainerElement( fvecStrA, "Fixed Vector A" ); 34 35 fvecStrA = fvecStrB; 36 fvecStrB = fvecStrC; 37 38 std::cout << "fvecStrC size = " << fvecStrC.size() << std::endl; 39 for( size_t i = 0 ; i < fvecStrC.size() ; i++ ){ 40 fvecStrC[i] = "TT"; 41 } 42 43 PrintContainerElement( fvecStrA, "Fixed Vector A" ); 44 PrintContainerElement( fvecStrB, "Fixed Vector B" ); 45 PrintContainerElement( fvecStrC, "Fixed Vector C" ); 46 47 std::cout << std::endl; 48 std::cout << "fvecStrA size = " << fvecStrA.size() << std::endl; 49 std::cout << "fvecStrB size = " << fvecStrB.size() << std::endl; 50 std::cout << "fvecStrC size = " << fvecStrC.size() << std::endl; 51 } 52 catch ( const std::exception &error ){ 53 std::cerr << error.what() << std::endl; 54 std::exit( EXIT_FAILURE ); 55 } 56 catch (...) { 57 std::cerr << "Unknown error precess halted." << std::endl; 58 std::exit( EXIT_FAILURE ); 59 } 60 61 return EXIT_SUCCESS; 62 } |
실행 결과는 아래와 같습니다.
---------- run ----------
fvecStrA was empty
Fixed Vector A :
Fixed Vector A : A A A A A A A A A A
fvecStrC size = 20
Fixed Vector A : B B B B B B B B B B B B B B B
Fixed Vector B : C C C C C C C C C C C C C C C C C C C C
Fixed Vector C : TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT TT
fvecStrA size = 15
fvecStrB size = 20
fvecStrC size = 20
출력 완료 (0초 경과) - 정상 종료
'C C++ - STL' 카테고리의 다른 글
STL - 15 STL contaner list 응용 - Composite pattern 활용 (0) | 2014.02.13 |
---|---|
STL - 14 STL container map 응용 - Singleton pattern 적용한 Config 처리 (0) | 2014.02.13 |
STL - 12 auto_ptr (0) | 2014.02.13 |
STL - 11 Function Object (함수 - 객체) (0) | 2014.02.13 |
STL - 10 Vector Container 구현 (0) | 2014.02.13 |