allocator(3C++) - allocator(3C++)
Standard C++ Library Copyright 1998, Rogue Wave Software, Inc.
NAMEallocator
- The default allocator object for storage management in Standard
Library containers.
SYNOPSIS
#include <memory>
template <class T>
class allocator;
DESCRIPTION
Containers in the Standard Library allow you control of storage manage‐
ment through the use of allocator objects. Each container has an allo‐
cator template parameter specifying the type of allocator to be used.
Every constructor, except the copy constructor, has an allocator param‐
eter, allowing you to pass in a specific allocator. A container uses
that allocator for all storage management.
The library has a default allocator, called allocator. This allocator
uses the global new and delete operators. By default, all containers
use this allocator. You can also design your own allocator, but if you
do so it must have an appropriate interface. The standard interface and
an alternate interface are specified below. The alternate interface
works on all supported compilers.
THE ALTERNATE ALLOCATOR
As of this writing, very few compilers support the full range of fea‐
tures needed by the standard allocator. If your compiler does not sup‐
port member templates, both classes and functions, then you must use
the alternate allocator interface. This alternate interface requires no
special features of a compiler and offers most of the functionality of
the standard allocator interface. The only thing missing is the ability
to use special pointer and reference types. The alternate allocator
fixes these as T* and T&. If your compiler supports partial specializa‐
tion, then even this restriction is removed.
From outside a container, use of the alternate allocator is transpar‐
ent. Simply pass the allocator as a template or function parameter
exactly as you would pass the standard allocator.
Within a container, the alternate allocator interface is more compli‐
cated to use because it requires two separate classes, rather than one
class with another class nested inside. If you plan to write your own
containers and need to use the alternate allocator interface, we recom‐
mend that you support the default interface as well, since that is the
only way to ensure long-term portability. See the User's Guide section
on building containers for an explanation of how to support both the
standard and the alternate allocator interfaces.
A generic allocator must be able to allocate space for objects of arbi‐
trary type, and it must be able to construct those objects on that
space. For this reason, the allocator must be type aware, but it must
be aware on any arbitrary number of different types, since there is no
way to predict the storage needs of any given container.
Consider an ordinary template. Although you may be able to instantiate
on any fixed number of types, the resulting object is aware of only
those types and any other types that can be built up from them (T*, for
instance), as well as any types you specify up front. This won't work
for an allocator, because you can't make any assumptions about the
types a container needs to construct. It may well need to construct Ts
(or it may not), but it may also need to allocate node objects and
other data structures necessary to manage the contents of the con‐
tainer. Clearly there is no way to predict what an arbitrary container
might need to construct. As with everything else within the Standard
Library, it is absolutely essential to be fully generic.
The Standard allocator interface solves the problem with member tem‐
plates. The precise type you are going to construct is not specified
when you create an allocator, but when you actually go to allocate
space or construct an object on existing space.
The alternate allocator interface uses a different technique. The
alternate interface breaks the allocator into two pieces: an interface
and an implementation. The interface is a template class containing a
pointer to an implementation. The implementation is a simple class pro‐
viding raw un-typed storage. Anything can be constructed on it. The
interface template types the raw storage based on the template parame‐
ter. Only the implementation object is passed into a container. The
container constructs interface objects as necessary, using the imple‐
mentation to manage the storage of data.
Since all interface objects use the one copy of the implementation
object to allocate space, that one implementation object manages all
storage acquisition for the container. The container makes calls to the
allocator_interface objects in the same way it would make calls to a
standard allocator object.
For example, if your container needs to allocate T objects and node
objects, you need to have two allocator_interface objects in your con‐
tainer:
allocator_interface<Allocator,T> value_allocator; allocator_inter‐
face<Allocator,node> node_allocator;
You then use the value_allocator for all allocation, construction, etc.
of values (Ts), and use the node_allocator object to allocate and deal‐
locate nodes.
The only significant drawback is the lack of special pointer types and
the inability to alter the behavior of the construct and destroy func‐
tions, since these must reside in the interface class. If your compiler
has partial specialization, then this restriction goes away, since you
can provide specialized interfaces along with your implementation.
STANDARD INTERFACE
template <class T>
class allocator {
typedef size_t size_type;
typedef ptrdiff_t difference_type;
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type;
template <class U> struct rebind {
typedef allocator<U> other;
};
allocator () throw();
allocator (const allocator&) throw ();
template <class U> allocator(const allocator<U>&) throw();
template <class U>
allocator& operator=(const allocator<U>&) throw();
~allocator () throw();
pointer address (reference) const;
const_pointer address (const_reference) const;
pointer allocate (size_type,
typename allocator<void>::const_pointer = 0);
void deallocate(pointer p, size_type n);
size_type max_size () const;
void construct (pointer, const T&);
void destroy (pointer);
};
// specialize for void:
template <> class allocator<void> {
public:
typedef void* pointer;
typedef const void* const_pointer;
// reference-to-void members are impossible.
typedef void value_type;
template <class U>
struct rebind { typedef allocator<U> other; };
};
// globals
template <class T, class U>
bool operator==(const allocator<T>&,
const allocator<U>&) throw();
template <class T, class U>
bool operator!=(const allocator<T>&,
const allocator<U>&) throw();
TYPESsize_type
Type used to hold the size of an allocated block of storage.
difference_type
Type used to hold values representing distances between storage addresses.
pointer
Type of pointer returned by allocator.
const_pointer
Const version of pointer.
reference
Type of reference to allocated objects.
const_reference
Const version of reference.
value_type
Type of allocated object.
template <class U> struct rebind;
Converts an allocator templatized on one type to an allocator templatized
on another type. This struct contains a single type member:
typedef allocator<U> other
CONSTRUCTORSallocator()
Default constructor.
template <class U>
allocator(const allocator<U>&)
Copy constructor.
DESTRUCTORS
~allocator()
Destructor.
MEMBER FUNCTIONS
pointer
address(reference x) const;
Returns the address of the reference x as a pointer.
const_pointeraddress(const_reference x) const;
Returns the address of the reference x as a const_pointer.
pointerallocate(size_type n,
typename allocator<void>::const_pointer p = 0)
Allocates storage. Returns a pointer to the first element in a block of
storage n*sizeof(T) bytes in size. The block is aligned appropriately for
objects of type T. Throws the exception bad_alloc if the storage is
unavailable. This function uses operator new(size_t). The second parameter
p can be used by an allocator to localize memory allocation, but the
default allocator does not use it.
voiddeallocate(pointer p, size_type n)
Deallocates the storage obtained by a call to allocate with arguments n and
p.
size_typemax_size() const;
Returns the largest size for which a call to allocate might succeed.
voidconstruct(pointer p, const T& val);
Constructs an object of type T2 with the initial value of val at the loca‐
tion specified by p. This function calls the placement new operator.
voiddestroy(pointer p)
Calls the destructor on the object pointed to by p, but does not delete.
ALTERNATE INTERFACE
class allocator
{
public:
typedef size_t size_type ;
typedef ptrdiff_t difference_type ;
allocator ();
~allocator ();
void * allocate (size_type, void * = 0);
void deallocate (void*);
};
template <class Allocator,class T>
class allocator_interface .
{
public:
typedef Allocator allocator_type ;
typedef T* pointer ; .
typedef const T* const_pointer ;
typedef T& reference ; .
typedef const T& const_reference ;
typedef T value_type ; .
typedef typename Allocator::size_type size_type ;
typedef typename Allocator::size_type difference_type ;
protected:
allocator_type* alloc_;
public:
allocator_interface ();
allocator_interface (Allocator*);
pointer address (T& x);
size_type max_size () const;
pointer allocate (size_type, pointer = 0);
void deallocate (pointer);
void construct (pointer, const T&);
void destroy (T*);
};
//
// Specialization
//
class allocator_interface <allocator,void>
{
typedef void* pointer ;
typedef const void* const_pointer ;
};
ALTERNATE ALLOCATOR DESCRIPTION
The description for the operations of allocator_interface<T> are gener‐
ally the same as for corresponding operations of the standard alloca‐
tor. The exception is that allocator_interface members allocate and
deallocate call respective functions in allocator, which are in turn
implemented like the standard allocator functions.
See the container section of the Class Reference for a further descrip‐
tion of how to use the alternate allocator within a user-defined con‐
tainer.
SEE ALSO
Containers
Rogue Wave Software 02 Apr 1998 allocator(3C++)