UE4 TSet
TSet 保存唯一值的合集,与 std::set 相似。TArray 通过 AddUnique 和 Contains 方法可用作集。然而 TSet 可更快实现这些操作,但无法像 TArray 那样将它们用作 UPROPERTY。TSet 不会像 TArray 那样将元素编入索引。
TSet<AActor*> ActorSet = GetActorSetFromSomewhere(); int32 Size = ActorSet.Num(); // 如集尚未包含元素,则将其添加到集 AActor* NewActor = GetNewActor(); ActorSet.Add(NewActor); // 检查元素是否已包含在集中 if (ActorSet.Contains(NewActor)) { // ... } // 从集移除元素 ActorSet.Remove(NewActor); // 从集移除所有元素 ActorSet.Empty(); // 创建包含 TSet 元素的 TArray TArray<AActor*> ActorArrayFromSet = ActorSet.Array();
需注意:TArray 是当前唯一能被标记为 UPROPERTY 的容器类。这意味着无法复制、保存其他容器类,或对其元素进行垃圾回收。
容器迭代器
使用迭代器可在容器的每个元素上进行循环。以下是使用 TSet 的迭代器语法范例。
void RemoveDeadEnemies(TSet<AEnemy*>& EnemySet) { // 从集的开头开始迭代到集的末端 for (auto EnemyIterator = EnemySet.CreateIterator(); EnemyIterator; ++EnemyIterator) { // * 运算符获得当前的元素 AEnemy* Enemy = *EnemyIterator; if (Enemy.Health == 0) { // RemoveCurrent 由 TSets 和 TMaps 支持 EnemyIterator.RemoveCurrent(); } } }
可结合迭代器使用的其他支持操作:
// 将迭代器移回一个元素 --EnemyIterator; // 以一定偏移前移或后移迭代器,此处的偏移为一个整数 EnemyIterator += Offset; EnemyIterator -= Offset; // 获得当前元素的索引 int32 Index = EnemyIterator.GetIndex(); // 将迭代器重设为第一个元素 EnemyIterator.Reset();
For-each 循环
迭代器很实用,但如果只希望在每个元素之间循环一次,则可能会有些累赘。每个容器类还支持 for each 风格的语法在元素上进行循环。TArray 和 TSet 返回每个元素,而 TMap 返回一个键值对。
// TArray TArray<AActor*> ActorArray = GetArrayFromSomewhere(); for (AActor* OneActor :ActorArray) { // ... } // TSet - 和 TArray 相同 TSet<AActor*> ActorSet = GetSetFromSomewhere(); for (AActor* UniqueActor :ActorSet) { // ... } // TMap - 迭代器返回一个键值对 TMap<FName, AActor*> NameToActorMap = GetMapFromSomewhere(); for (auto& KVP :NameToActorMap) { FName Name = KVP.Key; AActor* Actor = KVP.Value; // ... }
注意:auto 关键词不会自动指定指针/引用,需要自行添加。
通过 TSet/TMap(散列函数)使用您自己的类型
TSet 和 TMap 需要在内部使用 散列函数。如要创建在 TSet 中使用或作为 TMap 键使用的自定义类,首先需要创建自定义散列函数。通常会放入这些类型的多数 UE4 类型已定义其自身的散列函数。
散列函数接受到您的类型的常量指针/引用,并返回一个 uint64。此返回值即为对象的 散列代码,应该是对该对象唯一虚拟的数值。两个相等的对象固定返回相同的散列代码。
class FMyClass { uint32 ExampleProperty1; uint32 ExampleProperty2; // 散列函数 friend uint32 GetTypeHash(const FMyClass& MyClass) { // HashCombine 是将两个散列值组合起来的效用函数 uint32 HashCode = HashCombine(MyClass.ExampleProperty1, MyClass.ExampleProperty2); return HashCode; } // 出于展示目的,两个对象为相等 // 应固定返回相同的散列代码。 bool operator==(const FMyClass& LHS, const FMyClass& RHS) { return LHS.ExampleProperty1 == RHS.ExampleProperty1 && LHS.ExampleProperty2 == RHS.ExampleProperty2; } };
现在, TSet 和 TMap<fmyclass, ...=""> 在散列键时将使用适当的散列函数。如您使用指针作为键(即 TSet<FMyClass*>
),也将实现 uint32 GetTypeHash(const FMyClass* MyClass)
。
posted on 2016-08-08 15:14 pengyingh 阅读(3227) 评论(0) 编辑 收藏 举报