My last post, Stack Allocators for STL Containers, may have been a little confusing for some folks who are unfamiliar with the C++ Standard Library. Even those familiar with the Standard Library may not have dealt with allocators, so let’s take a step back and go over them.
If one looks into any STL documentation, one will notice an optional Allocator template parameter to most STL classes. In the G++ implementation of the STL, this Allocator parameter defaults to
std::allocator which is derived from the
__gnu_cxx::new_allocator in libstdc++. If you studied the
deallocate methods of the
__gnu_cxx::new_allocator class, it will tell you this base class indeed uses
delete to allocate and deallocate memory. I am going to leave it as an exercise for the reader to determine how
delete get memory from the system.
So why would one use another allocator besides the default? The reasons are aplenty, and here are some reasons that has had yours truly look into using non-default allocators.
- Reduce heap contention in a multi-threaded application.
- Reduce heap contention by reusing chunks of memory.
- Prevent memory fragmentation.
- Debugging and/or understanding memory usage in an application.
- Attempt to improve application performance (with debatable results).
std::allocator is used often enough that I believe its performance has been tuned fairly well in most implemenations, but what if I wanted to use a different allocator because of some specific need? I will use
std::vector to work through my examples since it is a class that everyone is familiar with. The following shows how an instance of
std::vector may be declared with and without the default allocator.
// the basic way that a vector will be declared std::vector<int> my_vector; // explicitly using std::allocator as the allocator. The instance is exactly the same as the one above std::vector<int, std::allocator> my_vector // using __gnu_cxx::malloc_allocator that comes with G++ std::vector<int, __gnu_cxx::malloc_allocator> my_vector; // passing an instance of std::allocator to std::vector. possible with G++ 4.x but not 3.x afaik. std::allocator my_allocator;
Using a non-default allocator can be as simple as that! The last example, as far as I am aware, is only possible with libstdc++ that comes with GCC 4.x but not 3.x. It may also be possible with other implementations of the STL besides the one provided by GCC, but I do not have any experience with them. Libstdc++ itself comes with several allocators, some of which you may find interesting to work with. The libstdc++ documentation gives a pretty good description of them, so I am going to let the reader peruse them at her leisure.