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)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值