Thanks for the link, looks interesting
.
I have to note though, that the memory usage of most STL containers can't be too surprising.
List is a doubly linked list, so each node will contain two 8 byte pointers (on 64-bit) as well as the value. Set is probably a binary search tree, so it will need at least left and right pointers. unordered_set might be a hash-table of some sort, which will need to not be full in order to be efficient.
If you change his custom allocator's constructor to print some information:
MemoryCountingAllocator() : base() {
std::cout << "+ Allocator for " << __PRETTY_FUNCTION__
<< ", with size " << sizeof(T) << std::endl;
}
You get something like:
Displaying memory usage in bytes.
Filling data structures with 1024 elements and reporting the per element memory usage.
+ Allocator for MemoryCountingAllocator<unsigned int>::MemoryCountingAllocator() [T = unsigned int], with size 4
memory usage per element of a vector<uint32_t> : 4
+ Allocator for MemoryCountingAllocator<std::_List_node<unsigned int> >::MemoryCountingAllocator() [T = std::_List_node<unsigned int>], with size 24
memory usage per element of a list<uint32_t> : 24
+ Allocator for MemoryCountingAllocator<unsigned int>::MemoryCountingAllocator() [T = unsigned int], with size 4
memory usage per element of a deque<uint32_t> : 4.64062
+ Allocator for MemoryCountingAllocator<std::__detail::_Hash_node<unsigned int, false> >::MemoryCountingAllocator() [T = std::__detail::_Hash_node<unsigned int, false>], with size 16
memory usage per element of an unordered_set<uint32_t> : 29.6016
+ Allocator for MemoryCountingAllocator<std::_Rb_tree_node<unsigned int> >::MemoryCountingAllocator() [T = std::_Rb_tree_node<unsigned int>], with size 40
memory usage per element of a set<uint32_t> : 40
Which shows that list, set, and unordered_set are allocating nodes for their respective implementations and not just uint32_t.