CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 1 of 1

Threaded View

  1. #1
    Join Date
    Aug 2002
    Location
    Madrid
    Posts
    4,588

    STL Allocator: What is the meaning of the 'Alloc' template parameter in 'vector'?

    Q: What is the meaning of the 'Alloc' template parameter in 'vector'?
    Q: How do I define my own allocator for use in STL containers?

    A: The whole concept is very well explained in Gabriel and Andreas' article about Allocators.

    The template parameter 'Alloc' specifies the type of allocator that the container should use to manage its memory. Every time the container needs a bit of memory, it will ask the allocator to retrieve it for him. The allocator usually just calls 'new' (and 'delete' when it has to free memory), but there can be more sophisticated strategies for allocators.

    Usually, you are fine with the standard allocator provided by your STL. However, at times you may need to specify the allocation strategy explicitly. In theory, writing a custom allocator is not very difficult, but the task is complicated by the fact that the standard C++ design relies on template member functions which quite a few compilers don't support (e.g. Visual C++ 6).

    A simple example for an allocator which never frees memory is this code (note that you need a recent compiler to get this to work):

    Code:
    #include <limits>
    
    const size_t TEST_SIZE = 10000;
    const double TIME_MULTIPLIER = 100.0;
    
    const size_t MAX_SIZE = (TEST_SIZE + 1) * 12;
    
    class MemoryPool
    {
      unsigned char  *m_data;
      size_t      m_top;
      int        m_refcount;
    public:
      MemoryPool()
      {
        m_data = new unsigned char[MAX_SIZE];
        m_top = 0;
        m_refcount = 0;
      }
      ~MemoryPool()
      {
        delete [] m_data;
      }
      void AddRef()
      {
        ++m_refcount;
      }
      void *alloc_mem(size_t n)
      {
        if ((MAX_SIZE - m_top) >= n) {
          size_t old_top = m_top;
          m_top += n;
          return m_data + old_top;
        } else {
          return 0;
        }
      }
      void Release()
      {
        if (--m_refcount == 0) {
          delete this;
        }
      }
    };
    
    template <class T>
    class MyAlloc {
    public:
      // type definitions
      typedef T        value_type;
      typedef T*       pointer;
      typedef const T* const_pointer;
      typedef T&       reference;
      typedef const T& const_reference;
      typedef std::size_t    size_type;
      typedef std::ptrdiff_t difference_type;
    
      // rebind allocator to type U
      template <class U >
      struct rebind {
        typedef MyAlloc< U > other;
      };
    
      // return address of values
      pointer address (reference value) const {
        return &value;
      }
      const_pointer address (const_reference value) const {
        return &value;
      }
    
      /* constructors and destructor
      * - nothing to do because the allocator has no state
      */
      MyAlloc() throw() {
        m_pPool = new MemoryPool;
        m_pPool->AddRef();
      }
      MyAlloc(const MyAlloc& src) throw() {
        m_pPool = src.m_pPool;
        m_pPool->AddRef();
      }
      template <class U >
      MyAlloc (const MyAlloc< U > &src) throw() {
        m_pPool = src.m_pPool;
        m_pPool->AddRef();
      }
      ~MyAlloc() throw() {
        m_pPool->Release();
      }
    
      // return maximum number of elements that can be allocated
      size_type max_size () const throw() {
        return MAX_SIZE / sizeof(T);
      }
    
      // allocate but don't initialize num elements of type T
      pointer allocate (size_type num, const void* = 0) {
        // print message and allocate memory with global new
        pointer ret = (pointer) m_pPool->alloc_mem(num * sizeof(T));
        return ret;
      }
    
      // initialize elements of allocated storage p with value value
      void construct (pointer p, const T& value) {
        // initialize memory with placement new
        new((void*)p)T(value);
      }
    
      // destroy elements of initialized storage p
      void destroy (pointer p) {
        // destroy objects by calling their destructor
        p->~T();
      }
    
      // deallocate storage p of deleted elements
      void deallocate (pointer p, size_type num) {
        // do not deallocate memory
      }
    
      MemoryPool  *m_pPool;
    };
    
    // return that all specializations of this allocator are interchangeable
    template <class T1, class T2>
    bool operator== (const MyAlloc<T1>&, const MyAlloc<T2>&) throw() {
      return true;
    }
    template <class T1, class T2>
    bool operator!= (const MyAlloc<T1>&, const MyAlloc<T2>&) throw() {
      return false;
    }

    Last edited by Andreas Masur; July 27th, 2005 at 01:07 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured