TinySTL 之 allocator 接口介绍

2022-5-26 大BUG阅读数:2019评论数:15   C++ 泛型编程 小项目
提示:此篇文章需要了解 C++ 泛型编程的一些概念才能看得懂本文章。

在学习 STL 设计的时候,最先学习的肯定是 allocator,这对应的是内存空间的分配和对象的建立。下面是 allocator 用到的接口

成员类型

alloctor 数据成员

类型 定义
value_type T
pointer T*
const_pointer const T*
reference const T&
const_reference const T&
size_type std::size
difference_type std::ptrdiff_t

成员函数

alloctor 成员函数

函数 定义
static T*
allocate();
分配未初始化的存储
static T*
allocate(size_type n);
分配未初始化的存储
static void
deallocate(T *ptr);
释放分配的内存
static void
deallocate(T *ptr, size_type n);
释放分配的内存
static void
construct(T *ptr);
释放分配的内存
static void
construct(T *ptr, const T &value);
在分配的内存创建对象
template <class... Args>
static void
construct(T *ptr, T &&value);
在分配的内存创建对象
static void
destroy(T *ptr);
析构在内存中分配的对象
static void
destroy(T *first, T *last);
析构在内存中分配的对象

这个接口的设计来自于 std::allocate 的接口介绍。

源码

关于源码部分的实现,主要借鉴于 STL 源码剖析这本书,并且 C++11 的一些新特性实现,通过模板 template<typename T >实现泛型编程。


#ifndef TINYSTL_ALLOCATOR_H_
#define TINYSTL_ALLOCATOR_H_

// 这个头文件包含一个模板类 allocator,用于管理内存的分配、释放,对象的构造、析构

#include "stl_construct.h"
#include "util.h"

namespace TinySTL
{

// 模板类:allocator
// 模板函数代表数据类型
template <typename T>
class allocator
{
public:
    typedef T            value_type;
    typedef T*           pointer;
    typedef const T*     const_pointer;
    typedef T&           reference;
    typedef const T&     const_reference;
    typedef size_t       size_type;
    typedef ptrdiff_t    difference_type;

    public:
    static T*   allocate();
    static T*   allocate(size_type n);

    static void deallocate(T* ptr);
    static void deallocate(T* ptr, size_type n);

    static void construct(T* ptr);
    static void construct(T* ptr, const T& value);
    static void construct(T* ptr, T&& value);

    template <typename... Args>
    static void construct(T* ptr, Args&& ...args);

    static void destroy(T* ptr);
    static void destroy(T* first, T* last);
};

template <typename T>
T* allocator<typename T>::allocate()
{
    return static_cast<T*>(::operator new(sizeof(T)));
}

template <typename T>
T* allocator<T>::allocate(size_type n)
{
    if (n == 0)
        return nullptr;
    return static_cast<T*>(::operator new(n * sizeof(T)));
}

template <typename T>
void allocator<T>::deallocate(T* ptr)
{
    if (ptr == nullptr)
        return;
    ::operator delete(ptr);
}

template <typename T>
void allocator<T>::deallocate(T* ptr, size_type /*size*/)
{
    if (ptr == nullptr)
        return;
    ::operator delete(ptr);
}

template <typename T>
void allocator<T>::construct(T* ptr)
{
    TinySTL::construct(ptr);
}

template <typename T>
void allocator<T>::construct(T* ptr, const T& value)
{
    TinySTL::construct(ptr, value);
}

template <typename T>
void allocator<T>::construct(T* ptr, T&& value)
{
    TinySTL::construct(ptr, TinySTL::move(value));
}

template <typename T>
template <typename...Args>
void allocator<T>::construct(T* ptr, Args&& ...args)
{
    TinySTL::construct(ptr, TinySTL::forward(args)...);
}

template <typename T>
void allocator<T>::destroy(T* ptr)
{
    TinySTL::destroy(ptr);
}

template <typename T>
void allocator<T>::destroy(T* first, T* last)
{
    TinySTL::destroy(first, last);
}

} // namespace TinySTL
#endif // !TINYSTL_ALLOCATOR_H_
                        

测试

测试的例子如下