BDE 4.14.0 Production release
|
Provide an STL-compatible proxy for bslma::Allocator
objects.
bsl::allocator
Canonical header: bsl_memory.h
This component is for internal use only. Please include <bsl_memory.h>
instead and use bsl::allocator
directly. This component provides an STL-compatible proxy for any allocator class derived from bslma::Allocator
. The proxy class, bsl::allocator
is a template that adheres to the allocator requirements defined in section 20.1.5 [lib.allocator.requirements] of the C++ standard. bsl::allocator
may be used to instantiate any class template that is parameterized by a standard allocator. The container is expected to allocate memory for its own use through the allocator. Different types of allocator use different allocation mechanisms, so this mechanism gives the programmer control over how the container obtains memory.
The bsl::allocator
template is intended to solve a problem created by the C++ standard allocator protocol. Since, in STL, the allocator type is specified as a container template parameter, the allocation mechanism becomes an explicit part of the resulting container type. Two containers cannot be of the same type unless they are instantiated with the same allocator type, and therefore the same allocation mechanism. bsl::allocator
breaks the connection between allocator type and allocation mechanism. The allocation mechanism is chosen at run-time by initializing (contrast with instantiating) the bsl::allocator
with a pointer to a mechanism object derived from bslma::Allocator
. Each class derived from bslma::Allocator
implements a specific allocation mechanism and is thus called a mechanism class within this component. The bsl::allocator
object forwards calls made through the standard allocator interface to the mechanism object with which it was initialized. In this way, two containers instantiated with bsl::allocator
can utilize different allocation mechanisms even though they have the same compile-time type. The default mechanism object, if none is supplied to the bsl::allocator
constructor, is bslma::Default::defaultAllocator()
.
Instantiations of bsl::allocator
have full value semantics (well-behaved copy construction, assignment, and tests for equality). Note, however, that a bsl::allocator
object does not "own" the bslma::Allocator
with which it is initialized. In practice , this means that copying a bsl::allocator
object does not copy its mechanism object and destroying a bsl::allocator
does not destroy its mechanism object. Two bsl::allocator
objects compare equal if and only if they share the same mechanism object.
The allocator requirements section of the C++ standard (section 20.1.5 [lib.allocator.requirements]) permits containers to assume that two allocators of the same type always compare equal. This assumption is incorrect for instantiations of bsl::allocator
. Therefore, any container (or other facility) that can use bsl::allocator
must operate correctly in the presence of non-equal bsl::allocator
objects. In practice, this means that a container cannot transfer ownership of allocated memory to another container unless the two containers use equal allocators. Two bsl::allocator
objects will compare equal if and only if they were initialized with the same mechanism object.
We first show how to define a container type parameterized with an STL-style allocator template parameter. For simplicity, we choose a fixed-size array to avoid issues concerning reallocation, dynamic growth, etc. Furthermore, we do not assume the bslma
allocation protocol, which would dictate that we pass-through the allocator to the parameterized T
contained type (see the bslma_allocator component and bslalg
package). The interface would be as follows:
The implementation is straightforward
Now we declare an allocator mechanism. Our mechanism will be to simply call global operator new
and operator delete
functions, and count the number of blocks outstanding (allocated but not deallocated). Note that a more reusable implementation would take an underlying mechanism at construction. We keep things simple only for the sake of this example.
The implementation is really straightforward:
Now we can create array objects with different allocator mechanisms. First we create an array, a1
, using the default allocator and fill it with the values [1 .. 5]
:
Then we create a copy of a1
using the counting allocator. The values of a1
and a2
are equal, even though they have different allocation mechanisms.