To manage all the memory allocation done by std::map
is it enough to store the map values as a pointer? I thought that std::map
might internally allocate tree nodes, for which it may use std::allocator
which might have class scope operator new
or operator delete
(not sure though).
To find this, I did a small test using a custom std conforming allocator that uses overloaded operator new
and operator delete
. Here is the code:
#include <iostream>
#include <memory>
#include <map>
#include <vector>
#include <algorithm>
int cnt = 0;
int num_elem = 0;
class A {
public:
int x;
char buffer[1000];
};
class OverloadNew {
public:
static void* newImpl(std::size_t sz,char const* file, int line){
void* ptr= std::malloc(sz);
cnt++;
std::cerr << file << ": " << line << " " << ptr << std::endl;
return ptr;
}
static void* operator new(std::size_t sz,char const* file, int line){
return newImpl(sz,file,line);
}
static void* operator new [](std::size_t sz,char const* file, int line){
return newImpl(sz,file,line);
}
static void operator delete(void* ptr) noexcept{
std::free(ptr);
}
};
template <class T>
class my_allocator {
public:
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;
my_allocator() {}
my_allocator(const my_allocator&) {}
pointer allocate(size_type n, const void * = 0) {
T* t = (T*)(OverloadNew::operator new(n*sizeof(T),__FILE__,__LINE__));
std::cout
<< "Inside Map allocate at address "
<< t << " (+)" << std::endl;
return t;
}
void deallocate(void* p, size_type) {
if (p) {
//free(p);
OverloadNew::operator delete(p);
std::cout
<< "Inside Map deallocate at address "
<< p << " (-)" <<
std::endl;
}
}
pointer address(reference x) const { return &x; }
const_pointer address(const_reference x) const { return &x; }
my_allocator<T>& operator=(const my_allocator&) { return *this; }
void construct(pointer p, const T& val)
{ new ((T*) p) T(val); }
void destroy(pointer p) { p->~T(); }
size_type max_size() const { return size_t(-1); }
template <class U>
struct rebind { typedef my_allocator<U> other; };
template <class U>
my_allocator(const my_allocator<U>&) {}
template <class U>
my_allocator& operator=(const my_allocator<U>&) { return *this; }
};
/* Object is a class that has a std::map member */
class Object {
public:
static void* newImpl(std::size_t sz,char const* file, int line) {
void* ptr= std::malloc(sz);
cnt++;
std::cerr <<"Inside Object class "<<file << ": " << line << " " << ptr << std::endl;
return ptr;
}
static void* operator new(std::size_t sz,char const* file, int line){
return newImpl(sz,file,line);
}
static void* operator new [](std::size_t sz,char const* file, int line){
return newImpl(sz,file,line);
}
static void operator delete(void* ptr) noexcept{
std::free(ptr);
}
void insertAnyOneElement() {
void* ptr = this->operator new(sizeof(A),__FILE__,__LINE__);
A* a = new(ptr) A();
Map.insert({num_elem++,a});
}
std::map<int,A*,std::less<int>,my_allocator<std::pair<const int, A*>>> Map;
};
int main() {
Object obj;
obj.insertAnyOneElement();
std::cout <<"total allocation :" << cnt << std::endl;
}
/*
Inside Object class temp.cpp: 116 0xe47018
temp.cpp: 55 0xe40ed0
Inside Map allocate at address 0xe40ed0 (+)
total allocation :2
Inside Map deallocate at address 0xe40ed0 (-)
*/
I found that the map
internally allocates new memory. I have two questions.
- Is there any other way to manage the memory allocation/deallocation done by
std::map
? - Is there any other memory allocation that can happen inside
std::map
class,(apart from the stored value), in another way, is the total allocation size of memory insidestd::map
is greater than the total size of the values being stored?
Thank You!
Aucun commentaire:
Enregistrer un commentaire