TInlineAllocator
- 分配器存储大小为NumInlineElements的定长数组,当实际存储的元素数量高于NumInlineElements时,会从SecondaryAllocator申请分配内存,默认情况下为堆分配器。
- 使用时机:非常了解数组中的最大数量元素
- TArray<Shape*, TInlineAllocator<16>> MyShapeArray;
- 前16个添加到数组的元素无动态分配
- 在17个元素之后,所有元素都被移动到第二分配器(比如堆分配器)以供存储
TInlineAllocator的数组
![](https://img.haomeiwen.com/i10337581/e956fb0c96dbd834.png)
-
内部第二分配器地址为:0x0000043f828d1ce0。 查看内存里面为1 2 3 4
image.png
TFixedAllocator 的数组
- TFixedAllocator 没有第二分配器;
-
如果固定存储没有空间了,会产生错误。
image.png
内部的2个内存分配器
// 数量少于NumInlineElements,使用此数组
TTypeCompatibleBytes<ElementType> InlineData[NumInlineElements];
// 数量超过NumInlineElements, 使用
typename SecondaryAllocator::template ForElementType<ElementType> SecondaryData;
ResizeAllocation的代码实现
- 针对不同情况使用InlineData 或 SecondaryData
- SecondaryData 默认为FDefaultAllocator
void ResizeAllocation(SizeType PreviousNumElements, SizeType NumElements,SIZE_T NumBytesPerElement)
{
// 检测数量是否满足.
if(NumElements <= NumInlineElements)
{
// SecondaryData被使用的情况
if(SecondaryData.GetAllocation())
{
// 新数据存入InlineData
RelocateConstructItems<ElementType>(
(void*)InlineData,
(ElementType*)SecondaryData.GetAllocation(),
PreviousNumElements);
// 释放老的元素
SecondaryData.ResizeAllocation(0,0,NumBytesPerElement);
}
}
else
{
// 数量超出时,SecondaryData未开启使用
if(!SecondaryData.GetAllocation())
{
// 扩容到NumElements
SecondaryData.ResizeAllocation(0,NumElements,NumBytesPerElement);
// inline数组元素移动到SecondaryData里
RelocateConstructItems<ElementType>((void*)SecondaryData.GetAllocation(),
GetInlineElements(), PreviousNumElements);
}
else
{
// SecondaryData已启用,扩容到NumElements
SecondaryData.ResizeAllocation(PreviousNumElements, NumElements, NumBytesPerElement);
}
}
}
RelocateConstructItems
- 破坏性的移动内存到自己内部
- 1 内部判断按情况 直接内存移动
- 2 执行新容器内的构造和老的析构
- 2中注意内存的同步移动。++ 和 --
if constexpr (UE::Core::Private::MemoryOps::TCanBitwiseRelocate<DestinationElementType, SourceElementType>::Value)
{
FMemory::Memmove(Dest, Source, sizeof(SourceElementType) * Count);
}
else
{
while (Count)
{
typedef SourceElementType RelocateConstructItemsElementTypeTypedef;
new (Dest) DestinationElementType(*Source);
++(DestinationElementType*&)Dest;
(Source++)->RelocateConstructItemsElementTypeTypedef::~RelocateConstructItemsElementTypeTypedef();
--Count;
}
}
获取分配器函数
// FContainerAllocatorInterface
FORCEINLINE ElementType* GetAllocation() const
{
return IfAThenAElseB<ElementType>(SecondaryData.GetAllocation(),GetInlineElements());
}
网友评论