内存分配器Allocator
- 容器都依赖一个分配器,扩容和回收内存都通过分配器实现
- 分配器是负责封装内存管理的对象]
- 标准库STL容器使用它们来管理容器内部的所有内存分配
- 动机是使容器完全独立于底层内存模型
- 让程序员控制容器内的内存分配,而不是用底层硬件的地址模型
TAllocatorTraitsBase
template <typename AllocatorType>
struct TAllocatorTraitsBase
{
enum { IsZeroConstruct = false };
enum { SupportsFreezeMemoryImage = false };
enum { SupportsElementAlignment = false };
};
ContainerAllocationPolicies.h 接口类定义
- 接口类 说明内存分配器是需要实现那些接口
- 基础类型,他们的大小和内存占用是一致的,而结构体sizeof可能会大于成员大小总和.
- 使用了内存对齐:让数据读取更高效,有些平台不对齐会崩溃
class FContainerAllocatorInterface
{
public:
using SizeType = int32;
enum { NeedsElementType = true };
enum { RequireRangeCheck = true };
// A class that receives both the explicit allocation and implicit
template<typename ElementType>
class ForElementType
{
void MoveToEmpty(ForElementType& Other);
// 需要明确类型 ElementType
template <typename OtherAllocatorType>
void MoveToEmptyFromOtherAllocator(typename OtherAllocatorType::template ForElementType<ElementType>& Other);
ElementType* GetAllocation() const;
// NumBytesPerElement - The number of bytes/element.
void ResizeAllocation(
SizeType PreviousNumElements, SizeType NumElements, SIZE_T NumBytesPerElement);
// exists SupportsElementAlignment == true 类似的重载函数就不列出
void ResizeAllocation(SizeType PreviousNumElements,SizeType NumElements,SIZE_T NumBytesPerElement,
uint32 AlignmentOfElement);
SizeType CalculateSlackReserve(
SizeType NumElements,SIZE_T NumBytesPerElement) const;
SizeType CalculateSlackShrink(
SizeType NumElements, SizeType CurrentNumSlackElements,SIZE_T NumBytesPerElement) const;
SizeType CalculateSlackGrow(
SizeType NumElements, SizeType CurrentNumSlackElements,SIZE_T NumBytesPerElement) const;
SIZE_T GetAllocatedSize(SizeType NumAllocatedElements, SIZE_T NumBytesPerElement) const;
bool HasAllocation() const;
SizeType GetInitialCapacity() const;
};
// NeedsElementType=false 时使用
typedef ForElementType<FScriptContainerElement> ForAnyElementType;
};
实现的内存分配器
// 对一些默认分配器的定义
template <int IndexSize> class TSizedDefaultAllocator : public TSizedHeapAllocator<IndexSize>
{ public: typedef TSizedHeapAllocator<IndexSize> Typedef; };
template<int IndexSize> class TSizedDefaultAllocator;
using FDefaultAllocator = TSizedDefaultAllocator<32>;
using FHeapAllocator = TSizedHeapAllocator<32>;
template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator>
using TInlineAllocator = TSizedInlineAllocator<NumInlineElements, 32, SecondaryAllocator>;
template <uint32 NumInlineElements, typename SecondaryAllocator = FDefaultAllocator64>
using TInlineAllocator64 = TSizedInlineAllocator<NumInlineElements, 64, SecondaryAllocator>;
UE的容器用的分配器定义
- TSizedDefaultAllocator 继承 TSizedHeapAllocator
- using FDefaultAllocator = TSizedDefaultAllocator<32>;
- FString = FDefaultAllocator
- TArray TSortedMap = FDefaultAllocator
- TSet TMap TMultiMap = FDefaultSetAllocator
/// @cond DOXYGEN_WARNINGS
template<int IndexSize> class TSizedDefaultAllocator;
using FDefaultAllocator = TSizedDefaultAllocator<32>;
using FDefaultAllocator64 = TSizedDefaultAllocator<64>;
class FDefaultSetAllocator;
class FString;
template<> struct TIsContiguousContainer<FString> { static constexpr bool Value = true; };
template<typename T, typename Allocator = FDefaultAllocator> class TArray;
template<typename T> using TArray64 = TArray<T, FDefaultAllocator64>;
template<typename T, typename SizeType = int32> class TArrayView;
template<typename T> using TArrayView64 = TArrayView<T, int64>;
template<typename T, typename SizeType = int32> using TConstArrayView = TArrayView<const T, SizeType>;
template<typename T> using TConstArrayView64 = TConstArrayView<T, int64>;
template<typename T> class TTransArray;
template<typename InKeyType, typename InValueType, bool bInAllowDuplicateKeys> struct TDefaultMapHashableKeyFuncs;
template<typename InKeyType, typename InValueType, typename SetAllocator = FDefaultSetAllocator, typename KeyFuncs = TDefaultMapHashableKeyFuncs<InKeyType, InValueType, false> > class TMap;
template<typename KeyType, typename ValueType, typename SetAllocator = FDefaultSetAllocator, typename KeyFuncs = TDefaultMapHashableKeyFuncs<KeyType, ValueType, true > > class TMultiMap;
template <typename T = void > struct TLess;
template <typename> struct TTypeTraits;
template<typename InKeyType, typename InValueType, typename ArrayAllocator = FDefaultAllocator, typename SortPredicate = TLess<typename TTypeTraits<InKeyType>::ConstPointerType> > class TSortedMap;
template<typename ElementType,bool bInAllowDuplicateKeys = false> struct DefaultKeyFuncs;
template<typename InElementType, typename KeyFuncs = DefaultKeyFuncs<InElementType>, typename Allocator = FDefaultSetAllocator> class TSet;
template<typename InElementType, typename InSizeType = int32> class TStridedView;
template<typename T, typename SizeType = int32> using TConstStridedView = TStridedView<const T, SizeType>;
/// @endcond
FString的分配器TSizedDefaultAllocator == TSizedHeapAllocator
- 使用的为类型为32的堆分配器 由FMemory管理控制内存
class FString
{
public:
using AllocatorType = TSizedDefaultAllocator<32>;
template <int IndexSize> class TSizedDefaultAllocator : public TSizedHeapAllocator<IndexSize>
{ public: typedef TSizedHeapAllocator<IndexSize> Typedef; };
网友评论