Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom allocator method is not called

I am trying to learn and write a self custom allocator - I was expecting that the cout statement should be printed but it never does - what is the wrong am I doing - how to write custom allocator:

#include <iostream>
#include <vector>

template < class T >
class MyAllocator : public std::allocator<T> {
public:
    T* allocate(size_t size)
    {
        std::cout << "Allocation request size " << size << std::endl;
        return new T[size];
    }

};

int main()
{
    std::vector <int, MyAllocator<int>> x;
    x.push_back(10);
    x.push_back(10);
    x.push_back(10);

    for (auto& var : x)
        std::cout << "Value " << var << std::endl;

}

Output

Value 10
Value 10
Value 10
like image 632
Programmer Avatar asked Jun 23 '26 17:06

Programmer


1 Answers

The inheritance of the standard allocator is not needed. Remove the inheritance : public std::allocator<T> and the compiler will be kind to inform you about what you missed to implement. Until C++17 the method construct must be implemented and it is used in std::vector, not allocate. Also value_type, deallocator and destroy are missing.

template< class U, class... Args >
void construct( U* p, Args&&... args );

Since you haven't implemented it and your allocator inherits the standard allocator, std::allocator::construct is called, that does not produce output.

Why you should not inherit std::allocator

The answer on this question is simple on the one hand and not simple in practice on the other hand.

  1. Like other classes in C++ standard library, std::allocator does not have a virtual destructor, so it should not be inherited, if it is not explicitly indicated like in std::enable_shared_from_this.
  2. Standard containers don't use class Allocator directly. They use std::allocator_traits. It helps to implement minimal user-defined allocators. If you implement only value_type, allocate and deallocate members of MyAllocator, std::allocator_traits<MyAllocator> makes MyAllocator fully conformed to C++ named requirements: Allocator.

    • Let look at your MyAllocator carefully. It inherits std::allocator and "replaces" std::allocator::allocate (2).
    • Let read std::allocator_traits::allocate (2) reference manual, that is called by std::vector:

      Calls a.allocate(n, hint) if possible. If not possible (e.g. a has no two-argument member function allocate()), calls a.allocate(n).

    What you have reached. You have implemented MyAllocator::allocate(std::size_t n) (2), but not MyAllocator::allocate(std::size_t n, const void* hint) (1), it is inherited from std::allocator. It is called from std::vector, that is not what you expected. If you had not inherited std::allocator, your implementation MyAllocator::allocate would be called.

like image 128
273K Avatar answered Jun 25 '26 08:06

273K