C++_泛型编程与标准库(四)

C++_泛型编程与标准库(四)

图中标红部分为自己的笔记理解

1、注意一个特化的typedefine

2、分配器

2.2、VC2019的allocator类

1. allocate调用operator new,再调用malloc

2. deallocate调用operator delete,operator delete又调用free

template <class _Ty>
class allocator {
public:
    static_assert(!is_const_v<_Ty>, "The C++ Standard forbids containers of const elements "
                                    "because allocator<const T> is ill-formed.");

    using _From_primary = allocator;

    using value_type = _Ty;

#if _HAS_DEPRECATED_ALLOCATOR_MEMBERS
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS typedef _Ty* pointer;
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS typedef const _Ty* const_pointer;

    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS typedef _Ty& reference;
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS typedef const _Ty& const_reference;
#endif // _HAS_DEPRECATED_ALLOCATOR_MEMBERS

    using size_type       = size_t;
    using difference_type = ptrdiff_t;

    using propagate_on_container_move_assignment = true_type;

#if _HAS_DEPRECATED_ALLOCATOR_MEMBERS
    using is_always_equal _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS = true_type;

    template <class _Other>
    struct _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS rebind {
        using other = allocator<_Other>;
    };

    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD _Ty* address(_Ty& _Val) const noexcept {
        return _STD addressof(_Val);
    }

    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD const _Ty* address(const _Ty& _Val) const noexcept {
        return _STD addressof(_Val);
    }
#endif // _HAS_DEPRECATED_ALLOCATOR_MEMBERS

    constexpr allocator() noexcept {}

    constexpr allocator(const allocator&) noexcept = default;
    template <class _Other>
    constexpr allocator(const allocator<_Other>&) noexcept {}
    _CONSTEXPR20_DYNALLOC ~allocator()       = default;
    _CONSTEXPR20_DYNALLOC allocator& operator=(const allocator&) = default;

    _CONSTEXPR20_DYNALLOC void deallocate(_Ty* const _Ptr, const size_t _Count) {
        // no overflow check on the following multiply; we assume _Allocate did that check
        _Deallocate<_New_alignof<_Ty>>(_Ptr, sizeof(_Ty) * _Count);//调用operator delete,operator delete又调用free
    }

    _NODISCARD _CONSTEXPR20_DYNALLOC __declspec(allocator) _Ty* allocate(_CRT_GUARDOVERFLOW const size_t _Count) {
        return static_cast<_Ty*>(_Allocate<_New_alignof<_Ty>>(_Get_size_of_n<sizeof(_Ty)>(_Count)));//此处调用template <size_t _Align, class _Traits = _Default_allocate_traits,enable_if_t<(!_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0>__declspec(allocator) _CONSTEXPR20_DYNALLOC void* _Allocate(const size_t _B}

#if _HAS_DEPRECATED_ALLOCATOR_MEMBERS
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD __declspec(allocator) _Ty* allocate(
        _CRT_GUARDOVERFLOW const size_t _Count, const void*) {
        return allocate(_Count);
    }

    template <class _Objty, class... _Types>
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS void construct(_Objty* const _Ptr, _Types&&... _Args) {
        ::new (_Voidify_iter(_Ptr)) _Objty(_STD forward<_Types>(_Args)...);
    }

    template <class _Uty>
    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS void destroy(_Uty* const _Ptr) {
        _Ptr->~_Uty();
    }

    _CXX17_DEPRECATE_OLD_ALLOCATOR_MEMBERS _NODISCARD size_t max_size() const noexcept {
        return static_cast<size_t>(-1) / sizeof(_Ty);
    }
#endif // _HAS_DEPRECATED_ALLOCATOR_MEMBERS
};

allocator的类调用的下列代码,而下列代码又调用了其他部分

template <size_t _Align, class _Traits = _Default_allocate_traits,
    enable_if_t<(!_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0>
__declspec(allocator) _CONSTEXPR20_DYNALLOC void* _Allocate(const size_t _Bytes) {
    // allocate _Bytes when !_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__
#if defined(_M_IX86) || defined(_M_X64)
#ifdef __cpp_lib_constexpr_dynamic_alloc // TRANSITION, GH-1532
    if (!_STD is_constant_evaluated())
#endif // __cpp_lib_constexpr_dynamic_alloc
    {
        if (_Bytes >= _Big_allocation_threshold) { // boost the alignment of big allocations to help autovectorization
            return _Allocate_manually_vector_aligned<_Traits>(_Bytes);
        }
    }
#endif // defined(_M_IX86) || defined(_M_X64)

    if (_Bytes != 0) {
        return _Traits::_Allocate(_Bytes);//此处调用struct _Default_allocate_traits
    }

    return nullptr;
}

_CONSTEXPR20_DYNALLOC void* _Allocate调用了Default_allocate_traits的operator new,可以看出最终分配器分配内存时调用的还是operator new,operator new调用malloc

struct _Default_allocate_traits {
    __declspec(allocator) static
#ifdef __clang__ // Clang and MSVC implement P0784R7 differently; see GH-1532
        _CONSTEXPR20_DYNALLOC
#endif // __clang__
        void* _Allocate(const size_t _Bytes) {
        return ::operator new(_Bytes);
    }
}

deallocate调用operator delete,operator delete又调用free

![](https://cdn.jsdelivr.net/gh/dwnb/Picture/20211019145916.png)template <size_t _Align, enable_if_t<(!_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__), int> = 0>
_CONSTEXPR20_DYNALLOC void _Deallocate(void* _Ptr, size_t _Bytes) noexcept {
    // deallocate storage allocated by _Allocate when !_HAS_ALIGNED_NEW || _Align <= __STDCPP_DEFAULT_NEW_ALIGNMENT__
#ifdef __cpp_lib_constexpr_dynamic_alloc // TRANSITION, GH-1532
    if (_STD is_constant_evaluated()) {
        ::operator delete(_Ptr);
    } else
#endif // __cpp_lib_constexpr_dynamic_alloc
    {
#if defined(_M_IX86) || defined(_M_X64)
        if (_Bytes >= _Big_allocation_threshold) { // boost the alignment of big allocations to help autovectorization
            _Adjust_manually_vector_aligned(_Ptr, _Bytes);
        }
#endif // defined(_M_IX86) || defined(_M_X64)
        ::operator delete(_Ptr, _Bytes);
    }
}

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-KLfzNuIc-1634628765574)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211019151620039.png)]

以上3个分配器并不好,不能减少额外开销,速度反而变慢了,GNU C++2.9版本有更棒的分配器,用的链表的形式。4.9版本进行了摒弃,把好的分配器放在了扩充分配器里

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值