标准库--默认分配器

发布时间:2024年01月19日

1.概述
标准库各类容器的操作过程往往需要空间分配,空间分配和释放需要分配器的支持。以下介绍标准库默认分配器实现。

2.默认分配器
基类部分

using std::size_t;
using std::ptrdiff_t;
template<typename _Tp>
inline _Tp* __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT
{
    return reinterpret_cast<_Tp*>(&const_cast<char&>(reinterpret_cast<const volatile char&>(__r)));
}

// 类型为_Tp的分配器的基类
template<typename _Tp>
class new_allocator
{
public:
    typedef size_t                                          size_type;
    typedef ptrdiff_t                                       difference_type;
    typedef _Tp*                                            pointer;
    typedef const _Tp*                                      const_pointer;
    typedef _Tp&                                            reference;
    typedef const _Tp&                                      const_reference;
    typedef _Tp                                             value_type;
    // 内部类型
    template<typename _Tp1>
    struct rebind {
        typedef new_allocator<_Tp1> other;
    };
    typedef std::true_type                                  propagate_on_container_move_assignment;
    // 默认构造
    new_allocator() _GLIBCXX_USE_NOEXCEPT { }
    // 拷贝构造
    new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { }
    // 普通构造--_Tp,_Tp1是相同类型
    // 拷贝构造--_Tp,_Tp1是不同类型
    template<typename _Tp1>
    new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { }
    // 析构
    ~new_allocator() _GLIBCXX_USE_NOEXCEPT { }
    // 返回引用对象的地址
    pointer address(reference __x) const _GLIBCXX_NOEXCEPT
    { return std::__addressof(__x); }
    // 返回常量引用的地址
    const_pointer address(const_reference __x) const _GLIBCXX_NOEXCEPT
    { return std::__addressof(__x); }
    // 分配功能
    pointer allocate(size_type __n, const void* = 0)
    {
        if (__n > this->max_size())
            std::__throw_bad_alloc();// 分配器对最大可分配尺寸有限制
        return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));// 通过::operator new实现空间分配
    }
    // 释放功能
    void deallocate(pointer __p, size_type)
    { ::operator delete(__p); }// 通过::operator delete实现空间释放

    size_type max_size() const _GLIBCXX_USE_NOEXCEPT
    { return size_t(-1) / sizeof(_Tp); }// 一次最多可分配的对象数目

    // 模板参数1:类型参数
    // 模板参数2:可变模板参数
    // 函数参数1:类型指针
    // 函数参数2:模板参数包,对包内每个元素添加&&修饰
    // 函数内通过::new((void *)__p) _Up(std::forward<_Args>(__args)...);实现在指定位置执行构造函数。采用了模板参数包的完美转发。
    template<typename _Up, typename... _Args>
    void construct(_Up* __p, _Args&&... __args)
    { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
    // 执行析构函数
    template<typename _Up>
    void destroy(_Up* __p) { __p->~_Up(); }
};

template<typename _Tp>
inline bool operator==(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
{ return true; }

template<typename _Tp>
inline bool operator!=(const new_allocator<_Tp>&, const new_allocator<_Tp>&)
{ return false; }

默认分配器

// 模板特化--特化就是模板参数类型做了指定或做了修饰(这个修饰会影响其可匹配到的范围)
template<>
class allocator<void>
{
public:
    typedef size_t                                          size_type;
    typedef ptrdiff_t                                       difference_type;
    typedef void*                                           pointer;
    typedef const void*                                     const_pointer;
    typedef void                                            value_type;
    template<typename _Tp1>
    struct rebind {
        typedef allocator<_Tp1> other;
    };
    typedef true_type                                       propagate_on_container_move_assignment;
};

template<typename _Tp>
using __allocator_base = __gnu_cxx::new_allocator<_Tp>;

// 用于分配类型_Tp元素的分配器
template<typename _Tp>
class allocator: public __allocator_base<_Tp>
{
public:
    typedef size_t                                      size_type;
    typedef ptrdiff_t                                   difference_type;
    typedef _Tp*                                        pointer;
    typedef const _Tp*                                  const_pointer;
    typedef _Tp&                                        reference;
    typedef const _Tp&                                  const_reference;
    typedef _Tp                                         value_type;
    // 内部的模板类
    template<typename _Tp1>
    struct rebind {
        typedef allocator<_Tp1> other;
    };
    typedef true_type                                   propagate_on_container_move_assignment;

    // 默认构造
    allocator() throw() { }
    // 拷贝构造
    allocator(const allocator& __a) throw() : __allocator_base<_Tp>(__a) { }
    // 普通构造--_Tp1和_Tp类型不同时
    // 拷贝构造--_Tp1和_Tp类型相同时
    template<typename _Tp1>
    allocator(const allocator<_Tp1>&) throw() { }
    // 析构
    ~allocator() throw() { }
};

// 支持==,!=运算符
template<typename _T1, typename _T2>
inline bool operator==(const allocator<_T1>&, const allocator<_T2>&)
{ return true; }
template<typename _Tp>
inline bool operator==(const allocator<_Tp>&, const allocator<_Tp>&)
{ return true; }
template<typename _T1, typename _T2>
inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&)
{ return false; }
template<typename _Tp>
inline bool operator!=(const allocator<_Tp>&, const allocator<_Tp>&)
{ return false; }

以上综合应用了各类语言的能力,如类型别名,::operator new::operator deleteplacement new,析构,模板特化,可变模板参数,模板参数包转发,完美转发,类型强制转换等。

文章来源:https://blog.csdn.net/x13262608581/article/details/135688967
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。