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版本进行了摒弃,把好的分配器放在了扩充分配器里