说明:容器是方便我们存储数据的载体,在虚幻中,为我们提供了三种容器。分别是TArray,TMap,TSet。首先虚幻提供的容器都是同质容器,只能用来存储相同类型的数据。三种容器具备不同的特性,针对不同的特性,我们可以根据使用场景选择操作的容器。

并且在虚幻定义了丰富的API供开发者使用

注意:在使用这三种容器的时候需要注意,只有TArray可以使用UPROPERTY宏说明

TArray

  • 最常用的数据容器,特点速度快,内存消耗小,安全性高。
  • TArray被称为同质容器:其所有元素均完全为相同类型。不能进行不同元素类型的混合
  • TArray被设计成值类型,无法被继承,不要使用new和delete在堆上进行创建销毁。元素也是数值类型,为容器拥有。TArray被销毁时元素也被销毁。从一个TArray创建新的TArray变量,将把元素复制到新的变量中,不存在共享状态。

初始化:

注意事项:容器在构建时,不要构建为堆对象!直接构建为栈对象!由于容器是模版类,在构建时必须指出存储数据类型。

// 容器需要构建为栈对象类型
    TArray<FString> Array; 
     //向容器添加5个元素,且值均为 Hello!
    Array.Init(TEXT("Hello!"), 5);

遍历数组:

  • Num函数可以获取TArray当前元素个数。TArray重载了运算符[],通过位置下标可以访问到对应位置元素
for (int i = 0; i < Array.Num(); i++) {
        UE_LOG(LogTemp, Log, TEXT("第%d值是:%s"),i,*Array[i]);
    }

输出结果:

LogTemp: 第0值是:Hello!
LogTemp: 第1值是:Hello!
LogTemp: 第2值是:Hello!
LogTemp: 第3值是:Hello!
LogTemp: 第4值是:Hello!

  • 借助新语法进行遍历
for (auto& val : Array) {
        UE_LOG(LogTemp, Log, TEXT("%s"), *val);
    }

输出结果:

LogTemp: Hello!
LogTemp: Hello!
LogTemp: Hello!
LogTemp: Hello!
LogTemp: Hello!

添加元素:

  • Add,Emplace,AddUnique函数均可向数组中添加元素(到末尾),元素被添加时,内存从分配器中被分配。Add和Emplace函数可达到同样的效果,但是存在细微不同。
  • Add函数将把一个元素类型实例复制(或移动)到数组中
  • Emplace添加元素到容器中,Add函数调用的是Emplace函数
  • AddUnique向容器中加入唯一元素,如果元素已经存在,则返回重复元素的位置
Array.Add(TEXT("Add01"));
    Array.Emplace(TEXT("Add02"));
    Array.AddUnique(TEXT("Add02"));
    Array.AddUnique(TEXT("Add03"));

输出结果:

LogTemp: 第0值是:Hello!
LogTemp: 第1值是:Hello!
LogTemp: 第2值是:Hello!
LogTemp: 第3值是:Hello!
LogTemp: 第4值是:Hello!
LogTemp: 第5值是:Add01
LogTemp: 第6值是:Add02
LogTemp: 第7值是:Add03

上面我们利用AddUnique又添加了一次Add02但是这里只有一个Add02;

Append:

  • Append函数可以复制普通的数组到容器中
  • 第一个参数,普通数组,第二个参数数组中元素的个数
FString StrArr[3]{ "1","2","3" };
    Array.Append(StrArr, ARRAY_COUNT(StrArr));

输出结果:

LogTemp: 第0值是:Hello!
LogTemp: 第1值是:Hello!
LogTemp: 第2值是:Hello!
LogTemp: 第3值是:Hello!
LogTemp: 第4值是:Hello!
LogTemp: 第5值是:1
LogTemp: 第6值是:2
LogTemp: 第7值是:3

Insert插入元素:

  • 允许在给定索引添加一个单一元素或元素数组的一个副本。
  • 如果插入位置超过容器的大小,将会报错!
Array.Insert(TEXT("ins01"), 3);

输出结果:

LogTemp: 第0值是:Hello!
LogTemp: 第1值是:Hello!
LogTemp: 第2值是:Hello!
LogTemp: 第3值是:ins01
LogTemp: 第4值是:Hello!
LogTemp: 第5值是:Hello!

SetNum:

主动设置容器的大小,如果长度大于原容器大小,空白位置将用模版类型默认对象填充。如果小于原容器大小,则超过设置大小的内容将被删除。

函数原型:第一个参数容器的大小,第二个是允许缩小容器当前元素数量

void SetNum(SizeType NewNum, bool bAllowShrinking = true)

使用:

Array.SetNum(3,true);

当你已经初始化过数组,但在后面又使用了 SetNum 且设置的长度比原长度小的时,数组会自动将超出的截去

如果设置的长度大于原长度,那么超出的部分就会被赋值为空

迭代器:

  • 迭代器(iterator)有时又称游标(cursor)是程序设计的软件设计模式,可在容器(container,例如链表或阵列)上遍访的接口,设计人员无需关心容器的内容。
  • TArray有两种迭代器,一种是可以通过迭代器更改元素内容,一种是只能读取元素不能修改元素。
  • 禁止在迭代器中修改容器的元素个数,禁止添加和移除元素
for (auto It = Array.CreateIterator();It; ++It)
    {
        // *It用来读取数据
        *It = FString(TEXT("cg01")); // 可以修改元素内容
        UE_LOG(LogTemp, Log, TEXT("%s"), **It);
    }
    for (auto It = Array.CreateConstIterator(); It; ++It)
    {
        // *It用来读取数据
        *It = FString(TEXT("cg01")); // 禁止修改元素内容
        UE_LOG(LogTemp, Log, TEXT("%s"), **It);
    }

输出结果:

LogTemp: 第0值是:cg01
LogTemp: 第1值是:cg01
LogTemp: 第2值是:cg01
LogTemp: 第3值是:cg01
LogTemp: 第4值是:cg01

转成普通数组:

返回类型指针,指针地址是数组中第一个元素的地址

FString* StrData = Array.GetData();

常规查询函数:

// 查询指定位置是否存在有效元素,返回布尔值
    Array.IsValidIndex(3);
    Array.Last();// 返回最后的元素
    Array.Last(3);// 返回倒数第三个元素
    Array.Top(); // 返回顶端元素
    // 检查是否包含给定的元素 返回布尔值
    Array.Contains(TEXT("Hello!"));
    // 查找是否包含给定的元素,并返回元素所在的位置,不包含返回-1
    Array.Find(TEXT("Hello!"));
    // 查找是否包含给定的元素,将位置索引设置到Index,返回布尔值
    int Index = 0;
    Array.Find(TEXT("Hello!"), Index)

常规移除函数:

TArray有Reset函数,清除内容,但保留空间

// 在容器中移除给定的元素,返回移除的个数
    Array.Remove(TEXT("Hello!"));
    // 移除数组中首个给定元素,成功返回1,失败返回0
    Array.RemoveSingle(TEXT("Hello!")); 
    Array.RemoveAt(3); // 返回给定位置的元素
    Array.Empty(); // 清空容器