Browse Source

feat: 添加 std::allocator 的一些解释代码

usuifohe 2 years ago
parent
commit
d174409ae3
2 changed files with 79 additions and 0 deletions
  1. BIN
      cpp/img/Memory_10.png
  2. 79 0
      cpp/内存机制.md

BIN
cpp/img/Memory_10.png


+ 79 - 0
cpp/内存机制.md

@@ -821,3 +821,82 @@ void* __CRTDECL operator new(size_t const size)
 
 > 不同的平台和版本可能有差异
 
+## std::allocator
+
+![](img/Memory_10.png)
+
+> 上图是 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`
+