|
|
@@ -821,3 +821,82 @@ void* __CRTDECL operator new(size_t const size)
|
|
|
|
|
|
> 不同的平台和版本可能有差异
|
|
|
|
|
|
+## std::allocator
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+> 上图是 vc6 下的 malloc
|
|
|
+
|
|
|
+| 颜色 | 作用 |
|
|
|
+| --- | --- |
|
|
|
+| 红色 | Cookie 标记的内存区块大小 |
|
|
|
+| 灰色 | 固定内容 用于 Debug |
|
|
|
+| 绿色 | pad 区域,用于判断整块内存是否16的倍数,不是的话用 pad 区域填充 |
|
|
|
+| 蓝色 | 真正对象会用到的内存空间 |
|
|
|
+
|
|
|
+参考上图,当使用 malloc 申请内存的时候,会额外申请一些内存空间用于缓存(Cookie)一些信息
|
|
|
+
|
|
|
+> Cookie 主要是记录区块有多大
|
|
|
+
|
|
|
+这些缓存信息带着一些额外的内存开销,如果申请一些比较小的内存,那么缓存信息所浪费的比值就比较大;反之如果申请内存较大,那么缓存信息所浪费的内存空间比值较小
|
|
|
+
|
|
|
+> 尤其是在软件开发中,我们每次申请的对象内存都不会太大,但是这种对象会很多,所以内存浪费就很明显
|
|
|
+
|
|
|
+不同编译器下所带的标准库中的分配器的实现方式可能都不相同
|
|
|
+
|
|
|
+下面的代码是 macos 中 xcode 中 `std::allocator` 的实现方法
|
|
|
+
|
|
|
+```cpp
|
|
|
+template <class _Tp>
|
|
|
+class _LIBCPP_TEMPLATE_VIS allocator
|
|
|
+ : private __non_trivial_if<!is_void<_Tp>::value, allocator<_Tp> >
|
|
|
+{
|
|
|
+ static_assert(!is_volatile<_Tp>::value, "std::allocator does not support volatile types");
|
|
|
+public:
|
|
|
+ typedef size_t size_type;
|
|
|
+ typedef ptrdiff_t difference_type;
|
|
|
+ typedef _Tp value_type;
|
|
|
+ typedef true_type propagate_on_container_move_assignment;
|
|
|
+ typedef true_type is_always_equal;
|
|
|
+
|
|
|
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
+ allocator() _NOEXCEPT = default;
|
|
|
+
|
|
|
+ template <class _Up>
|
|
|
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
+ allocator(const allocator<_Up>&) _NOEXCEPT { }
|
|
|
+
|
|
|
+ _LIBCPP_NODISCARD_AFTER_CXX17 _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
+ _Tp* allocate(size_t __n) {
|
|
|
+ if (__n > allocator_traits<allocator>::max_size(*this))
|
|
|
+ __throw_bad_array_new_length();
|
|
|
+ if (__libcpp_is_constant_evaluated()) {
|
|
|
+ return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp)));
|
|
|
+ } else {
|
|
|
+ return static_cast<_Tp*>(_VSTD::__libcpp_allocate(__n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp)));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#if _LIBCPP_STD_VER > 20
|
|
|
+ // 特殊处理
|
|
|
+#endif
|
|
|
+
|
|
|
+ _LIBCPP_INLINE_VISIBILITY _LIBCPP_CONSTEXPR_SINCE_CXX20
|
|
|
+ void deallocate(_Tp* __p, size_t __n) _NOEXCEPT {
|
|
|
+ if (__libcpp_is_constant_evaluated()) {
|
|
|
+ ::operator delete(__p);
|
|
|
+ } else {
|
|
|
+ _VSTD::__libcpp_deallocate((void*)__p, __n * sizeof(_Tp), _LIBCPP_ALIGNOF(_Tp));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+#if _LIBCPP_STD_VER <= 17 || defined(_LIBCPP_ENABLE_CXX20_REMOVED_ALLOCATOR_MEMBERS)
|
|
|
+ // 被 C++ 20 移除的一些内容
|
|
|
+#endif
|
|
|
+};
|
|
|
+```
|
|
|
+
|
|
|
+稍微扫一下上面的代码,很明显可以定位到 `allocate` 函数和 `deallocate` 函数, 根据函数的实现其本质也很简单就是调用 `::operator new` 和 `::operator delete`
|
|
|
+
|
|
|
+所以**某些情况**下 `allocator` 其实几乎啥都没做,没有做内存管理,而是直接调用全局的 `new` 和 `delete`
|
|
|
+
|