Is there a malloc/free based allocator in the STL? If not, does anyone know of a simple copy/paste one? I need it for a map that must not call new/delete.
First, I'd note that changing the allocator for the map itself won't change the allocation used by the objects stored in the map. For example, if you do something like:
std::map<std::string, int, my_allocator<std::pair<const std::string, int> > m;
The map itself will allocate memory using the specified allocator, but when the std::string
s in the map allocate memory, they'll still use the default allocator (which will use new
and delete
. So, if you need to avoid new
and delete
in general, you have to ensure that not only the map itself uses the right allocator, but that any objects it stores do the same (I know that's probably stating the obvious, but I've overlooked it, so maybe it's worth mentioning).
With that proviso, on with the code:
#ifndef ALLOCATOR_H_INC_
#define ALLOCATOR_H_INC_
#include <stdlib.h>
#include <new>
#include <limits>
namespace JVC {
template <class T>
struct 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(){}
~allocator() throw() {}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
pointer allocate(size_type s, void const * = 0) {
if (0 == s)
return NULL;
pointer temp = (pointer)malloc(s * sizeof(T));
if (temp == NULL)
throw std::bad_alloc();
return temp;
}
void deallocate(pointer p, size_type) {
free(p);
}
size_type max_size() const throw() {
return std::numeric_limits<size_t>::max() / sizeof(T);
}
void construct(pointer p, const T& val) {
new((void *)p) T(val);
}
void destroy(pointer p) {
p->~T();
}
};
}
#endif
And, a little test code:
#include <map>
#include <vector>
#include <iostream>
#include <string>
#include <iterator>
#include "allocator.h"
// Technically this isn't allowed, but it's only demo code, so we'll live with it.
namespace std {
std::ostream &operator<<(std::ostream &os, std::pair<std::string, int> const &c) {
return os << c.first << ": " << c.second;
}
}
int main() {
std::map<std::string, int, std::less<std::string>,
JVC::allocator<std::pair<const std::string, int> > > stuff;
stuff["string 1"] = 1;
stuff["string 2"] = 2;
stuff["string 3"] = 3;
std::copy(stuff.begin(), stuff.end(),
std::ostream_iterator<std::pair<std::string, int> >(std::cout, "\n"));
return 0;
}
ostream_iterator
than all the production C++ code written to date. ;-) –
Antilogy numberic_limits
is in the <limits>
header –
Irretentive std::string
is a typedef for std::basic_string<chat, std::Allocator<char> >
. You can define your own std::basic_string<char, my_allocator>
, and that will use the allocator you specify--but it'll also be largely incompatible with most existing string implementations. –
Landowner Indeed, as @MichaelBurr suggests, Stephen J, Lavavej's 'mallocator' is what you're looking for. I just got updated and prettied-up code for it in this answer by @Arnaud today, do have a look.
© 2022 - 2024 — McMap. All rights reserved.
malloc()
andfree()
callnew
anddelete
rather than the other way around. – MatherlyThe functions calloc(), malloc(), and realloc() do not attempt to allocate storage by calling ::operator new()
, andThe function free() does not attempt to deallocate storage by calling ::operator delete().
(That's not to argue that it hasn't been done, only that doing so violates the requirements of the standard). – Landowner