Implement a simple STL allocator

Time:2021-10-24

1. General

This paper implements a simple allocator and briefly explains the internal implementation process of new / delete.

2. A simple STL allocator

STL allocator is the space configurator in the container. STD:: allocator is the default of the standard library. Its main functions are memory allocation and release, object construction and deconstruction. It is hidden inside the container. Generally, we don’t need to pay attention to it, but it is necessary to understand its implementation.
The simple allocator implemented is as follows (see reference 1 for details):

#ifndef MYALLOCATOR_H_
#define MYALLOCATOR_H_

#include 
#include 
#include 
#include 
#include 

namespace MA
{

template
inline T* _allocate(ptrdiff_t size, T*)
{
    T* tmp = static_cast(::operator new(static_cast(size * sizeof(T))));
    if(nullptr == tmp)
    {
        std::cerr << "out of memory" << std::endl;
    }

    return tmp;
}

template
inline void _deallocate(T* buffer)
{
    ::operator delete(buffer);
}

template
inline void _constructor(T1* p, const T2& value)
{
    new(p) T1(value);
}

template
inline void _destroy(T* p)
{
    p->~T();
}

template
struct allocator
{
    using value_type = T;
    using pointer = T*;
    using const_pointer = const T*;
    using reference = T&;
    using const_reference = const T&;
    using size_type = size_t;
    using difference_type = ptrdiff_t;

    template
    struct rebind
    {
        using other = allocator;
    };

    pointer allocate(size_type n, const void* hint = 0)
    {
        return _allocate(static_cast(n), static_cast(nullptr));
    }

    void deallocate(pointer p, size_type n)
    {
        _deallocate(p);
    }

    void construct(pointer p, const T& value)
    {
        _constructor(p, value);
    }

    void destroy(pointer p)
    {
        _destroy(p);
    }

    pointer address(reference x)
    {
        return static_cast(&x);
    }

    const_pointer const_address(const_reference x)
    {
        return static_cast(&x);
    }

    size_type max_size() const
    {
        return static_cast(UINT_MAX / sizeof(T));
    }
};

}

#endif /* MYALLOCATOR_H_ */

The main interfaces and their functions are as follows:

  1. Pointer allocate (size_type n, const void * hint = 0): allocate memory to store n instances of type T and return pointers to it
  2. Void deallocate (pointer P, size_type n): free the allocated memory
  3. Void construct (pointer P, const T & value): construct an object using the value pointed to by P
  4. Void destroy (pointer P): call the destructor that P points to the object

The user-defined allocator is used as follows (see reference 2 for the complete code):

#include "MyAllocator.h"
#include 
#include "gtest/gtest.h"

struct MyAllocatorTest : testing::Test
{
};

TEST_F(MyAllocatorTest, test_for_my_allocator)
{
    int arr[3] {1, 2, 3};
    std::vector> vec{arr, arr + 3};
    ASSERT_EQ(1, vec[0]);
    ASSERT_EQ(2, vec[1]);
    ASSERT_EQ(3, vec[2]);
}

3. New / delete analysis

It involves memory allocation and release, object construction and deconstruction, which needs to explain new / delete.
New is a built-in keyword in C + +. It mainly does three things:

  1. Call the corresponding operator new operator to allocate memory
  2. Call the corresponding constructor
  3. Returns a pointer to the construction object type

Delete is a built-in keyword in C + +. It mainly does two things:

  1. Call the corresponding destructor
  2. Call the corresponding operator delete operator to free up memory

The following is an example:

string *p = new string("Hello");
equals to: 
void *memory = ::operator new(sizeof(string)); //  Call:: operator new to allocate memory
string::string("Hello"); //  Call the constructor to put the string into the allocated memory 
string *p = static_ cast(memory); //  Make the P pointer point to the newly constructed object
delete p;
equals to: 
p->string::~string("Hello"); //  Call destructor
::operator delete(memory); //  Call:: operator delete to free memory

4. Summary

This paper explores the implementation mechanism of STD:: allocator through a simple allocator, which can have a preliminary understanding of STD:: allocator. Of course, this is far from the actual implementation, which needs to be further studied. Please look forward to more in-depth analysis.

5. References

  1. Hou Jie, STL source code analysis
  2. https://github.com/mzh19940817/MyAllocator

Welcome to criticize, comment and reprint (please indicate the source). Thank you!