I'm confused about the difference between the STL allocator and the Operator new.
In the book I'm reading it's solution to "find a way of getting and manipulating uninitialized storage" was replacing "new" with allocator.
I'm wondering, what is the difference? Why isn't using "new" and "delete" sufficient for uninitialized storage? And what advantage does allocator have over "new" and "delete."
An allocator gets the right kind of memory from the right place. the default does the same as ::operator new, but if you need a custom pool with a custom kind of pointer to that pool, a suitable allocator will do that for you. The code that uses the new pool will remain unchanged.
It's all about providing tools that help to keep large complex programs simple.
So after reading a little more about it something in your post that sticks out is
It's all about providing tools that help to keep large complex programs simple
so there isn't any advantage in using allocator aside from using it as an abstraction to make allocating memory cleaner.
So the difference between these blocks of code is just the interface.
1 2 3 4 5 6 7 8 9
void vector::reserve(int newalloc)
if (newalloc<=space) return; // never decrease allocation
double * p = newdouble[newalloc]; // allocate new space
for (int i=0; i<sz; ++i) p[i] = elem[i];// copy old elements
delete elem; // deallocate old space
elem = p;
space = newalloc;
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
template<class T, class A>
void vector<T,A>::reserve(int newalloc)
if(newalloc<=space) return; // no need to do anything if allocation decreases
// alloc new uninitialize space to store values
T * p = alloc.allocate(newalloc); // allocate new space
// copy elements values into newly created uninitialize space
for(int i=0; i<sz; ++i)alloc.construct(&p[i],elem[i]); // copy
// destroy old space that element is currently in
for(int i=0; i<sz; ++i)alloc.destroy(&elem[i]); // destroy
// free the space so it can be pontential used and to prevent memory leaks
alloc.deallocate(elem,space); // deallocate old space
elem = p; // copy elem to newly created space
space = newalloc; // resize space
You will no doubt have noticed that the STL containers take an allocator as a parameter and can report what allocator they're using.
This means that collections can be placed in a memory pool, it's not just about your object.
For example, you can use a custom memory pool to manage a shared memory block. That doesn't really have an equivalent concept with just using new/delete.
In your example, for T = double, and using the default allocator on some system, the two are probably equivalent, subtleties aside.
One thing you've overlooked in your simplification is the allocator returns raw memory that doesn't have a constructed object in it, so you can't just call operator= to place an object there. You have to use a placement constructor to copy the object there, hence the call to construct.
Similarly, destroy calls the objects destructor without trying to return the memory to some pool.