TArray
TArray:负责同类型对象(元素)序列的所有权和组织权。
一、创建数组
// 创建数组
TArray<int32> IntArray;
InArray.Init(10, 5); //InArray = [10, 10, 10, 10, 10]
二、填充数组
1、Add()
和 Emplace
:末尾添加元素
Add()
和Emplace()
方法向数组末尾添加元素
Add()
添加时创建临时变量,复制到数组中Emplace()
不创建临时变量,在容器内 “原地构造” 元素
// Add 和 Emplace
TArray<FString> StrArr;
StrArr.Add (TEXT("Hello"));
StrArr.Emplace(TEXT("World")); // StrArr == ["Hello","World"]
2、Append()
:添加其他TArray
中的多个元素
TArray<FString> StrArr = {TEXT("Hello"), TEXT("World")};
TArray<FString> NewStrArr = {TEXT("Unreal"), TEXT("Engine")};
StrArr.Append(NewStrArr); // StrArr = ["Hello", "World", "Unreal", "Engine"]
3、Insert()
:插入元素
Insert()
给定索引处添加元素
StrArr.Insert(TEXT("Brave"), 1); // StrArr = ["Hello", "Brave", "World", "Unreal", "Engine"]
4、SetNum()
:设置数组数量
SetNum()
设置数组元素的数量
- 如新数量大于当前数量,则使用元素类型的默认构造函数新建元素;
- 如新数量小于当前数量,
SetNum
将移除元素。
StrArr.SetNum(8); // StrArr = [Hello, Brave, World, Unreal, Engine, , , ]
StrArr.SetNum(3); // StrArr = [Hello, Brave, World]
三、迭代
TArray<int32> Arr = {1, 2, 3}
// auto 范围遍历
for (auto& i : Arr)
{
i = ...;
}
// 基于索引迭代
for (int32 i = 0; i < Arr.Nums(); ++i)
{
Arr[i] = ...;
}
// 迭代器迭代
for (auto Iter = Arr.CreateIterator(); Iter; ++Iter) // CreateConstIterator 只读迭代器
{
*Iter = ...;
}
四、排序
Sort()
方法可对数组排序
StrArr.Sort(); // 按元素的 运算符< 进行排序
// StrArr = ["Brave", "Engine", "Hello", "Unreal", "World"]
auto SortFunc = [](const FString& A, const FString& B)
{
return A.Len() > B.Len();
};
StrArr.Sort(SortFunc); // 按自定义排序规则排序
// StrArr = ["Engine", "Unreal", "Brave", "Hello", "World"] 同长度元素内部顺序可能不同
StrArr.StableSort(SortFunc) // 稳定排序
// StrArr = ["Engine", "Unreal", "Brave", "Hello", "World"]
五、查询
1、Num()
:查询数组数量
Num()
查询TArray
元素个数
int32 ArrLength = StrArr.Num(); // ArrLength = 5
2、GetData()
:获取数组指针
GetData()
获取TArray
指针;如容器为常量,则返回的指针也为常量。
FString* StrPtr = StrArr.GetData(); // 返回数组指针 StrPtr[0] = StrArr[0] = Engine
运算符[]
获取指定索引位置元素,会返回引用,可修改容器中的元素;如容器为常量,返回常量引用。
3、Last()
和Top()
:获取最后元素
Last()
从数组末端反向索引,索引默认为零。Top()
方法同Last()
,区别是不接受索引
FString Elem1 = StrArr[1]; // Elem1 = "Unreal"
StrArr[3] = StrArr[3].ToUpper(); // StrArr = ["Engine", "Unreal", "Brave", "HELLO", "World"]
FString ElemEnd = StrArr.Last(); // ElemEnd = "World"
FString ElemEnd1 = StrArr.Last(1); // ElemEnd1 = "HELLO"
FString ElemTop = StrArr.Top(); // ElemTop = "World"
4、Contains()
和Find()
:是否存在特定元素
Contains()
查询数组是否包含指定元素
bool bHello = StrArr.Contains(TEXT("Hello")); // bHello == true
bool bGoodBye = StrArr.Contains(TEXT("GoodBye")); // bGoodbye == false
Find()
查找元素是否存在,并返回其找到的首个元素的索引;FindLast()
会返回其找到的最后一个元素的索引;
如果不将索引作为显式参数传递,这两个函数会将元素索引作为返回值返回;如未找到元素,将返回特殊 INDEX_NONE
值:
int32 Index;
StrArr.Add(TEXT("HELLO"));
bool bFind = StrArr.Find(TEXT("HELLO"), Index); // bFind = true, Index = 3
bFind = StrArr.FindLast(TEXT("HELLO"), Index); // bFind = true, Index = 5
Index = StrArr.Find(TEXT("HELLO")); // Index = 3;
六、移除
1、Remove()
:移除全部特定元素
Remove()
移除根据元素类型的运算符==
移除所有与提供元素相等的元素
TArray<int32> IntArr = {10, 20, 30, 5, 10, 15, 20, 25, 30};
IntArr.Remove(20); // IntArr = [10, 30, 5, 10, 15, 25, 30]
2、RemoveSingle()
:移除首个特定元素
IntArr.RemoveSingle(30); // IntArr = [10, 5, 10, 15, 25, 30]
3、RemoveAt()
:移除索引位置上元素
IntArr.RemoveAt(2); // IntArr = [10, 5, 15, 25, 30]
4、RomoveAll()
:移除满足条件的所有元素
IntArr.RemoveAll([](int32 val)
{
return val % 3 == 0;
}); // IntArr = [10, 5, 25]
上述方法移动过程存在开销。如不需要剩余元素排序,可使用 RemoveSwap
、RemoveAtSwap
和 RemoveAllSwap
函数减少此开销。此类方法其不保证剩余元素的排序,因此可更快地完成任务
5、Empty()
:移除所有元素
七、运算符
1、赋值运算符=
赋值运算符=
可以为数组进行赋值,可以理解为一次深拷贝
IntArr = {1, 2, 3};
TArray<int32> NewIntArr = IntArr;
NewIntArr[0] = 5;
// IntArr = [1, 2, 3]
// NewIntArr = [5, 2, 3]
2、运算符+=
运算符+=
等同于Append()
方法
NewIntArr += IntArr; // NewIntArr = [5, 2, 3, 1, 2, 3]
3、MoveTemp
TArray
支持移动语义MoveTemp
,移动后,源数组为空
IntArr = MoveTemp(NewIntArr);
// IntArr = [5, 2, 3, 1, 2, 3]
// NewIntArr = []
4、==
和!=
运算符==
和!=
可用于比较TArray
,只有元素的排序和数量相同时,两个数组中元素通过自身类型的运算符==
相比
八、堆
1、数组转换为堆
TArray
有支持二叉堆数据结构的函数,Heapify()
方法可将数组转换为堆,方法支持接受谓词,无谓词默认使用元素类型的运算符<
来确定排序
TArray<int32> HeapArr = {10, 9, 8, 7, 6, 5, 4, 3, 2, 1};
HeapArr.Heapify(); // HeapArr = [1, 2, 4, 3, 6, 5, 8, 10, 7, 9]
2、HeapPush()
:添加新元素到堆
HeapPush()
可将新元素添加到堆,并对其他节点重新排序
HeapArr.HeapPush(4); // HeapArr = [1, 2, 4, 3, 4, 5, 8, 10, 7, 9, 6]
3、HeapPop()
和HeapPopDiscard()
:移除堆顶节点
HeapPop()
和HeapPopDiscard()
用于移除堆的顶部节点,前者引用元素类型返回顶部元素,后者只移除。移除后会对其他节点重新排序
int32 TopNode; // TopNode = 1
HeapArr.HeapPop(TopNode); // HeapArr = [2, 3, 4, 6, 4, 5, 8, 10, 7, 9]
4、移除给定索引元素
HeapRemoveAt()
删除数组中给定索引处的元素,并对其他节点重新排序
HeapArr.HeapRemoveAt(1); // HeapArr = [2, 4, 4, 6, 9, 5, 8, 10, 7]
5、HeapTop()
:获取顶部节点,无需变更数组
TopNode = HeapArr.HeapTop(); // TopNode = 2
九、Slack(空闲容量)
Slack
理解为容器中已分配内存但未被用到的那些元素存储槽,默认构建的数组不分配内存,Slack初始为零。
1、GetSlack()
:获取当前Slack量
GetSlack()
可以获取当前数组的Slack量,Max()
可以获取当前容器最大分配元素量,Num()
即为两者之差。
TArray<int32> SlackArray;
// SlackArray.GetSlack() == 0
// SlackArray.Num() == 0
// SlackArray.Max() == 0
SlackArray.Add(1);
// SlackArray.GetSlack() == 3
// SlackArray.Num() == 1
// SlackArray.Max() == 4
SlackArray.Add(2);
SlackArray.Add(3);
SlackArray.Add(4);
SlackArray.Add(5);
// SlackArray.GetSlack() == 17
// SlackArray.Num() == 5
// SlackArray.Max() == 22
2、Reserve()
:分配内存
Reserve
可分配内存,无需添加元素,如果分配的内存比当前小,则无效。
SlackArr.Reserve(25); // Num:5, Max:25, Slack:20
SlackArr.Reserve(1); // Num:5, Max:25, Slack:20
3、Empty()
和Reset()
:清空数组(重新分配内存)
Empty()
和Reset()
方法清空容器为容器重新分配内存,区别是Reset()
方法分配时不会释放先前的内存。
SlackArr.Empty(10); // Num:0, Max:10, Slack:10
SlackArr.Reset(10); // Num:0, Max:22, Slack:22
4、Shrink()
:移除所有Slack,不影响数组中元素
SlackArr = {1, 2, 3, 4}; // Num:4, Max:22, Slack:18
SlackArr.Shrink(); // Num:4, Max:4, Slack:0
十、其他
1、Swap()
交换元素值
SlackArr.Swap(1, 3); // SlackArr = [1, 4, 3, 2]
2、GetAllocatedSize()
:数组内存占用量
GetAllocatedSize()
估算当前数组内存占用量,数组类型Sizeof()
的值 × 数组的Max()
SIZE_T CountBytes = MyArr.GetAllocatedSize(); // 16