Standard C++ Library
Copyright 1998, Rogue Wave Software, Inc.
NAME
allocator
- 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 management through the use of allocator objects.
Each container has an allocator template parameter specify-
ing the type of allocator to be used. Every constructor,
except the copy constructor, has an allocator parameter,
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 alter-
nate 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 features needed by the standard allocator. If your
compiler does not support member templates, both classes and
functions, then you must use the alternate allocator inter-
face. 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 com-
piler supports partial specialization, then even this
restriction is removed.
From outside a container, use of the alternate allocator is
transparent. 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 complicated 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 recommend 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 arbitrary 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 alloca-
tor, because you can't make any assumptions about the types
a container needs to construct. It may well need to con-
struct 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 container. 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 templates. The precise type you are going to con-
struct 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 tech-
nique. 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 providing raw un-typed
storage. Anything can be constructed on it. The interface
template types the raw storage based on the template
parameter. Only the implementation object is passed into a
container. The container constructs interface objects as
necessary, using the implementation to manage the storage of
data.
Since all interface objects use the one copy of the imple-
mentation 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 container:
allocator_interface<Allocator,T> value_allocator;
allocator_interface<Allocator,node> node_allocator;
You then use the value_allocator for all allocation, con-
struction, etc. of values (Ts), and use the node_allocator
object to allocate and deallocate nodes.
The only significant drawback is the lack of special pointer
types and the inability to alter the behavior of the con-
struct and destroy functions, since these must reside in the
interface class. If your compiler has partial specializa-
tion, 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();
TYPES
size_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 allo-
cator templatized on another type. This struct contains a
single type member:
typedef allocator<U> other
CONSTRUCTORS
allocator()
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_pointer
address(const_reference x) const;
Returns the address of the reference x as a
const_pointer.
pointer
allocate(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 unavail-
able. 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.
void
deallocate(pointer p, size_type n)
Deallocates the storage obtained by a call to allocate
with arguments n and p.
size_type
max_size() const;
Returns the largest size for which a call to allocate
might succeed.
void
construct(pointer p, const T& val);
Constructs an object of type T2 with the initial value of
val at the location specified by p. This function calls
the placement new operator.
void
destroy(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 generally the same as for corresponding operations of
the standard allocator. The exception is that
allocator_interface members allocate and deallocate call
respective functions in allocator, which are in turn imple-
mented like the standard allocator functions.
See the container section of the Class Reference for a
further description of how to use the alternate allocator
within a user-defined container.
SEE ALSO
Containers