【UE5转载】UE5中的数组TArray

TArray 是UE 用来替换C++ 标准库中的vector。STL 虽然十分优秀,但是用在游戏领域,则存在内存分配上的问题,主要体现在内存利用率不够高、分配速度慢。笔者曾在最短路算法中使用vector 等标准库容器,32G 内存直接溢出,后改用C 语言的数组实现,内存使用量才1G 多。为了解决以上问题,UE 开发出了TArray、TMap、TSet等容器,以全面替代STL 中的vector、map、set等。

本文将总结TArray 的常见用法,总的来说,TArray 的用法与vector 相似,但也有较大区别。

一,TArray 的创建、初始化、赋值
TArray 的创建、初始化、赋值的主要形式如下。其中,列表既可以用作构造函数的参数,也可以用来初始化和赋值。Init() 可以在TArray 在放置若干个相同元素。

TArray<FString> Arr;
//Arr is []

TArray<FString> SecArr({ TEXT("Are"), TEXT("you"), TEXT("OK") });
//SecArr is [Are you OK]

TArray<FString> ThirdArr = { TEXT("Are"), TEXT("you"), TEXT("OK") };
//ThirdArr is [Are you OK]

ThirdArr.Init(TEXT("Hello"), 3);
//ThirdArr is [Hello Hello Hello]

Arr = { TEXT("Hello"), TEXT("World") };
//Arr is [Hello World]

二,TArray 的元素添加
添加单个元素
向TArray 中添加单个元素,有很多中方法:Add、Push、Emplace、AddUnique、Insert。在具体使用上,它们也有一些差别,归纳如下:

前四种是在数组尾部追加元素,Insert 可在数组的任意位置插入元素;
Add 和 Push类似,但是将元素复制或移动到数组中,而Emplace 则使用给定参数构建元素类型的新实例;通常来说,Emplace 的效率高于Add;
如果不存在相同元素(用运算符=判断),AddUnique 才会向数组中添加元素。
各个函数的使用方式如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") };
Arr.Add(TEXT(","));
//Arr is [Are you OK ,]

Arr.Push(TEXT("Hello"));
//Arr is [Are you OK , Hello]

Arr.Emplace(TEXT("World"));
//Arr is [Are you OK , Hello World]

Arr.AddUnique(TEXT(","));
//Arr is [Are you OK , Hello World]
Arr.AddUnique(TEXT("I"));
//Arr is [Are you OK , Hello World I]

Arr.Insert(TEXT("Head"), 0);
//Arr is [Head Are you OK , Hello World I]

添加多个元素
向数组中添加多个元素,可采用Append() 方法或 += 操作符完成,使用方法如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") };

TArray<FString> SecArr({ TEXT("How"), TEXT("Do"), TEXT("You") });
Arr.Append(SecArr);
//Arr is [Are you OK How Do You]

TArray<FString> ThirdArr({ TEXT("I"), TEXT("Am"), TEXT("Fine") });
Arr += ThirdArr;
//Arr is [Are you OK How Do You I Am Fine]

三,TArray 的三种遍历
TArray 的遍历一共有三种形式:范围for 循环、索引、迭代器,这一点上和vector 类似。下面展示了这几种遍历的使用方法。

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") };

for (auto& s : Arr)
{
	UE_LOG(LogTemp, Warning, TEXT("%s"), *s);
}

for (int i = 0; i < Arr.Num(); i++)
{
	UE_LOG(LogTemp, Warning, TEXT("%d: %s"), i, *Arr[i]);
}

for (auto It = Arr.CreateIterator(); It; ++It)
{
	UE_LOG(LogTemp, Warning, TEXT("%s"), *(*It));
}

四,TArray 的三种排序
TArry的排序方法也有三种:Sort、HeapSort、StableSort。他们的简单使用方法如下:

Arr.Sort();
Arr.HeapSort();
Arr.StableSort();

三者并不相同,存在如下差异:

Sort 基于快速排序,是不稳定的排序;
HeapSort 基于堆排序,是不稳定的排序;
StableSort 基于归并排序,是稳定的排序。
默认情况下,上述三种排序方法都是使用元素类型的 < 运算符进行排序。我们可以使用lambda 自定义排序规则,如下,我们根据字符串长度对FString 排序。

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") ,TEXT("Hello"), TEXT("World") };

Arr.StableSort(
	[](const FString& A, const FString& B) {return A.Len() < B.Len(); }
);
//Arr is [OK Are you Hello World]

五,TArray 的元素删除
删除元素的方法比较多,有Remove()、RemoveSingle()、RemoveAll()、RemoveAt()、Empty()。总结下来,它们的用法如下:

Remove(Str): 删除数组中所有与 Str 相同的元素,是否相同用 == 运算符判断;
RemoveSingle(Str):删除数组中第一个与 Str 相同的元素,是否相同用 == 运算符判断;
RemoveAll(lambda):删除数组中的多个元素,删除规则由lambda 表达式指定;
RemoveAt(i):删除数组中索引为 i 的元素;
Empty():并不是判断数组为空,而是清空所有元素;
Remove(Str) 与 RemoveSingle(Str) 的区别在于是删除单个元素,还是所有元素;
Remove(Str) 与 RemoveAll(lambda) 的区别在于删除规则的不同。
代码演示如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
Arr.Remove(TEXT("OK"));
//Arr is [Are you]

Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
Arr.RemoveSingle(TEXT("OK"));
//Arr is [Are you OK]

Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
Arr.RemoveAll([](const FString& Str) {return Str.Len() == 2; });
//Arr is [Are you]

Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
Arr.RemoveAt(0);
//Arr is [you OK OK]

Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
Arr.Empty();
//Arr is []

六,TArray 的查询
根据索引获取元素对象的引用:[] 运算符、Last()、Top()
使用 [] 运算符、Last()、Top()都可以根据索引获取数组中的元素,并且获取的都是元素的引用,也就是说我们可以直接修改数组中的元素。如下代码所示,执行 Arr[0] = Arr[1] 之后,第 0 个元素的值也变成第 1 个元素的了;执行 Arr.Top() = Arr[1] 之后,最后一个元素的值也变成第 1 个元素的了。这三个方法的联系与区别如下:

Arr[i] 获取的是顺数第 i 个元素;
Last(i) 获取的是倒数第 i 个元素 ;
Top() 不能带参数,实际效果完全和 Last()一样。
三个方法的具体用法如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") ,TEXT("Hello"), TEXT("World") };
Arr[0] = Arr[1];
// Arr is [you you OK Hello World]

UE_LOG(LogTemp, Warning, TEXT("%s"), *Arr.Last());	//Output: World
UE_LOG(LogTemp, Warning, TEXT("%s"), *Arr.Last(1));	//Output: Hello
UE_LOG(LogTemp, Warning, TEXT("%s"), *Arr.Top());	//Output: World

Arr.Top() = Arr[1];
// Arr [you you OK Hello you]

判断元素是否存在:Contains()、ContainsByPredicate()
判断数组中是否存在某元素,使用的方法是Contains() 及其变体ContainsByPredicate()。ContainsByPredicate() 允许使用一元谓词指定判断规则。具体用法如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK") ,TEXT("Hello"), TEXT("World") };
bool bExist = Arr.Contains(TEXT("Are"));
bool bContain = Arr.ContainsByPredicate(
	[](const FString& Str) {return Str.Len() == 3; }
);

查找元素所在的索引:Find()、FindLast()、IndexOfByKey()、IndexOfByPredicate()
查找元素所在的索引,使用的方法是Find()、FindLast()、IndexOfByKey()、IndexOfByPredicate()。如果查找成功,则返回元素所在的索引;查找失败,则返回 INDEX_NONE(值为-1的宏)。他们的用法总结如下:

Find(Str):返回数组中第一个与 Str 相同的元素的索引,是否相同用 == 运算符判断;
FindLast(Str):返回数组中最后一个与 Str 相同的元素的索引,是否相同用 == 运算符判断;
IndexOfByKey(Str):与 Find(Str) 一样;
IndexOfByPredicate(lambda):IndexOfByKey 的lambda 版,用lambda 表达式来指定查找元素的规则。
代码示例如下:

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
int Index = Arr.Find(TEXT("OK"));
//Index is 2

Index = Arr.Find(TEXT("I"));
//Index is INDEX_NONE

Index = Arr.FindLast(TEXT("OK"));
//Index is 3

Index = Arr.IndexOfByKey(TEXT("OK"));
//Index is 2

Index = Arr.IndexOfByPredicate([](const FString& Str) {return Str.Len() == 3; });
//Index is 0

查找元素对象:FindByKey()、FindByPredicate()、FilterByPredicate()
FindByKey()、FindByPredicate()、FilterByPredicate() 可用来获取数组中的元素对象。FindByKey()、FindByPredicate() 获取的都是指向元素的指针,FilterByPredicate() 获取的是所有符合条件的元素,用法总结如下:

FindByKey(Str):获取数组中第一个与 Str 相同的元素的指针,获取失败返回nullptr;
FindByPredicate(lambda):FindByKey 的lambda 版,用lambda 表达式来指定查找元素的规则;
FilterByPredicate(lambda):获取数组中所有使lambda 表达式为true 的元素,但这些元素都是拷贝,返回一个数组。

TArray<FString> Arr = { TEXT("Are"), TEXT("you"), TEXT("OK"), TEXT("OK") };
FString* StrPtr = Arr.FindByKey(TEXT("OK"));
//StrPtr 是一个指向字符串"OK"的指针

StrPtr = Arr.FindByPredicate([](const FString& Str) {return Str.Len() == 3; });
//StrPtr 是一个指向字符串"Are"的指针

TArray<FString> StrArr = Arr.FilterByPredicate([](const FString& Str) {return Str.Len() == 3; });
//StrArr is [Are you]
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值