学习虚幻C++开发日志——TSet
TSet
官方文档:虚幻引擎中的Set容器 | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com)
TSet
是通过对元素求值的可覆盖函数,使用数据值本身作为键,而不是将数据值与独立的键相关联。
默认情况下,TSet
不支持重复的键,但使用模板参数可激活此行为。
TSet
是一种快速容器类,用于在排序不重要的情况下存储唯一元素。TSet
可以非常快速地添加、查找和删除元素(恒定时间)。在大多数情况下,只需要一种参数——元素类型。但是,TSet
可配置各种模板参数来改变其行为,使其更全面。除了可指定从 DefaultKeyFuncs
的派生结构体来提供散列功能,还可允许集合中的多个键拥有相同的值。它和其它容器类一样,可设置自定义内存分配器来存储数据。
和 TArray
一样,TSet
是同质容器。TSet
也是值类型,支持常规复制、赋值和析构函数操作,以及其元素较强的所有权。TSet
被销毁时,其元素也将被销毁。键类型也必须是值类型。
TSet
使用散列,即如果给出了 KeyFuncs
模板参数,该参数会告知集合如何从某个元素确定键,如何比较两个键是否相等,如何对键进行散列,以及是否允许重复键。它们默认只返回对键的引用,使用 运算符==
对比相等性,使用非成员函数 GetTypeHash
进行散列。默认情况下,集合中不允许有重复的键。如果您的键类型支持这些函数,则可以将其用作集合键,无需提供自定义 KeyFuncs
。要写入自定义 KeyFuncs
,可扩展 DefaultKeyFuncs
结构体。
最后,TSet
可通过任选分配器控制内存分配行为。标准虚幻引擎4(UE4)分配器(如 FHeapAllocator
和 TInlineAllocator
)不能用作 TSet
的分配器。实际上,TSet
使用集合分配器,该分配器可定义集合中使用的散列桶数量以及用于存储元素的标准UE4分配器。
与 TArray
不同的是,内存中 TSet
元素的相对排序既不可靠也不稳定,对这些元素进行迭代很可能会使它们返回的顺序和它们添加的顺序有所不同。这些元素也不太可能在内存中连续排列。集合中的后台数据结构是稀疏数组(在数组中有空位。从集合中移除元素时,稀疏数组中会出现空位)。将新的元素添加到阵列可填补这些空位。
但是,即便 TSet
不会打乱元素来填补空位,指向集元素的指针仍然可能失效,因为如果存储器被填满,又添加了新的元素,整个存储可能会重新分配。
1.创建和填充集合
创建一个MapActor类并继承于Actor,其与TArray创建方法一样就不一一详细介绍;
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void InitSet();
源文件增添代码:
void ASetActor::InitSet()
{TSet<FString> FruitSet;//此处的元素按插入顺序排列,但不保证这些元素在内存中实际保留此排序。//如果是新集合,可能会保留插入排序,但插入和删除的次数越多,新元素不出现在末尾的可能性越大。FruitSet.Add(TEXT("Banana"));FruitSet.Add(TEXT("Grapefruit"));FruitSet.Add(TEXT("Pineapple"));// FruitSet == [ "Banana", "Grapefruit", "Pineapple" ]FruitSet.Add(TEXT("Pear"));FruitSet.Add(TEXT("Banana"));//此处与上面的键重复因此覆盖了,但此处会触发扩容// FruitSet == [ "Banana", "Grapefruit", "Pineapple", "Pear" ]// Note:Only one banana entry.//此处,参数直接传递给键类型的构造函数。这可以避免为该值创建临时 FString。//与 TArray 不同的是,只能使用单一参数构造函数将元素放到集合中。FruitSet.Emplace(TEXT("Orange"));//追加元素,用Emplace函数代替Add避免插入集合时创造临时文件// FruitSet == [ "Banana", "Grapefruit", "Pineapple", "Pear", "Orange" ]TSet<FString> FruitSet2;FruitSet2.Emplace(TEXT("Kiwi"));FruitSet2.Emplace(TEXT("Melon"));FruitSet2.Emplace(TEXT("Mango"));FruitSet2.Emplace(TEXT("Orange"));FruitSet.Append(FruitSet2);// FruitSet == [ "Banana", "Grapefruit", "Pineapple", "Pear", "Orange", "Kiwi", "Melon", "Mango" ]
}
注意元素以及Num的变化,从而去理解TSet键的原理 (使用数据值本身作为键)
2.编辑UPROPERTY TSet
如果用 UPROPERTY
宏和一个可编辑的关键词(EditAnywhere
、EditDefaultsOnly
或 EditInstanceOnly
)标记 TSet
,则可在虚幻编辑器中添加和编辑元素。
Actor类头文件增添代码:
public:UPROPERTY(BlueprintReadWrite,EditAnyWhere,Category = SetExample)TSet<FString> MyFruitSet;
在蓝图可编辑操作
此处为FString,但其也可以放结构体
3.迭代
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void LoopSet();
源文件增添代码:
void ASetActor::LoopSet()
{TSet<FString> FruitSet;FruitSet.Add(TEXT("Banana"));FruitSet.Add(TEXT("Grapefruit"));FruitSet.Add(TEXT("Pineapple"));//依次输出元素for (auto& Elem :FruitSet)//此处的auto可换为FString,其本质时自动推导类型{FPlatformMisc::LocalPrint(*FString::Printf(TEXT(" \"%s\"\n"),*Elem));}//创建迭代器(如为CreateConstIterators 函数则为常量迭代器)for (auto It = FruitSet.CreateIterator(); It; ++It){//注意后面*(*It),第一个*是把FString类型变成TCHAR,第二个是指针,因为迭代器It是地址FPlatformMisc::LocalPrint(*FString::Printf(TEXT("(%s)\n"),*(*It)));}for (auto It = FruitSet.CreateConstIterator(); It; ++It){FPlatformMisc::LocalPrint(*FString::Printf(TEXT("(%s)\n"),*(*It)));}
}
4.查询
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void QuerySet();
源文件增添代码:
void ASetActor::QuerySet()
{TSet<FString> FruitSet;bool bHave=false;FruitSet.Add(TEXT("Banana"),&bHave);//此处bHave为falseFruitSet.Add(TEXT("Grapefruit"));FruitSet.Add(TEXT("Pineapple"));FruitSet.Add(TEXT("Banana"),&bHave);//此处使得bHave为trueint32 Count = FruitSet.Num();// Count == 3//要确定集合是否包含特定元素,可按如下所示调用 Contains 函数bool bHasBanana = FruitSet.Contains(TEXT("Banana"));bool bHasLemon = FruitSet.Contains(TEXT("Lemon"));// bHasBanana == true// bHasLemon == false//使用 FSetElementId 结构体可查找集合中某个键的索引。FSetElementId SetElementId=Fruit.Add(TEXT("Water"));//FSetElementId为标识符,此处SetElementId={Index=3}FruitSet[SetElementId]+=TEXT("Modify");//此处将Index为3的元素进行修改为"WaterModify"//使用 Find 函数查找一次即可完成这些行为。//如果集合中包含该键,Find 将返回指向元素数值的指针。如果映射不包含该键,则返回null。对常量集合调用Find,返回的指针也将为常量。FString* PtrBanana = FruitSet.Find(TEXT("Banana"));FString* PtrLemon = FruitSet.Find(TEXT("Lemon"));// *PtrBanana == "Banana"// PtrLemon == nullptr//Array 函数会返回一个 TArray,其中填充(覆盖,即使有元素在内)了 TSet 中每个元素的一份副本。因此元素的生成数量将始终等于集合中的元素数量TArray<FString> FruitArray = FruitSet.Array();//用Array函数转换为TArray数组
}
5.移除
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void RemoveSet();
源文件增添代码:
void ASetActor::RemoveSet()
{TSet<FString> FruitSet;FruitSet.Reserve(4);FruitSet.Add(TEXT("Banana"));FruitSet.Add(TEXT("Grapefruit"));FruitSet.Add(TEXT("Pineapple"));FruitSet.Add(TEXT("GG"));FruitSet.Add(TEXT("HH"));FruitSet.Add(TEXT("JJ"));//Remove函数有两种使用参数方法FruitSet.Remove(FSetElementId::FromInterger(0));//通过索引移除第一个元素//Remove函数会返回已删除元素的数量。int32 GGNum=FruitSet.remove(TEXT("GG"));//GGNum=1int32 MMNum=FruitSet.remove(TEXT("MM"));//MMNum=0TSet<FString> FruitSet1=FruitSet;FruitSet1.Reset();//将集合中的所有元素移除,但内存空间还在TSet<FString> FruitSet2=FruitSet;FruitSet2.Empty(0);//此操作是将元素及其内存空间都删除
}
6.排序&运算符&Slack
6.1排序
TSet
可以排序。排序后,迭代集合会以排序的顺序显示元素,但下次修改集合时,排序可能会发生变化。由于排序不稳定,可能按任何顺序显示集合中支持重复键的等效元素。
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void SortSet();
源文件增添代码:
void ASetActor::SortSet()
{TSet<FString>FruitSet={ "Orange","Pear", "Melon", "Grapefruit", "Mango", "Kiwi"};FruitSet.Sort([](const FString& A, const FString& B) {return A > B; // sort by reverse-alphabetical order});// FruitSet == [ "Pear", "Orange", "Melon", "Mango", "Kiwi", "Grapefruit" ] (order is temporarily guaranteed)//Sort 函数使用指定排序顺序的二进制谓词FruitSet.Sort([](const FString& A, const FString& B) {return A.Len() < B.Len(); // sort strings by length, shortest to longest});// FruitSet == [ "Pear", "Kiwi", "Melon", "Mango", "Orange", "Grapefruit" ] (order is temporarily guaranteed)
}
6.2运算符
其和 TArray
一样,TSet
是常规值类型,可通过标准复制构造函数或赋值运算符进行复制。因为集合严格拥有其元素,复制集合的操作是深层的,所以新集合将拥有其自身的元素副本。
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void OpeatorSet();
源文件增添代码:
void ASetActor::SortSet()
{TSet<FString>FruitSet={ "Orange","Pear", "Melon", "Grapefruit", "Mango", "Kiwi"};TSet<FString> NewSet = FruitSet;//在新的进行增删改查NewSet.Add(TEXT("Apple"));NewSet.Remove(TEXT("Pear"));
}
//在移除目录处也有提及
6.3Slack
其用法与TMap容器大致相似
Actor类头文件增添代码:
public:UFUNCTION(BlueprintCallable)void SlackSet();
源文件增添代码:
void ASetActor::SortSet()
{TSet<FString>FruitSet={ "Orange","Pear", "Melon", "Grapefruit", "Mango", "Kiwi"};//Reset函数可在不取消任何内存的情况下移除集合中的所有元素,从而产生slackFruitSet.Reset();FruitSet.Reserve(10);//在原基础上追加预分配10个内存for (int32 i = 0; i < 10; ++i){FruitSet.Add(FString::Printf(TEXT("Fruit%d"), i));}
// FruitSet == [ "Fruit9", "Fruit8", "Fruit7" ..."Fruit2", "Fruit1", "Fruit0" ]// Remove every other element from the set.for (int32 i = 0; i < 10; i += 2){FruitSet.Remove(FSetElementId::FromInteger(i));}
// FruitSet == ["Fruit8", <invalid>, "Fruit6", <invalid>, "Fruit4", <invalid>, "Fruit2", <invalid>, "Fruit0", <invalid> ]//Shrink裁剪元素FruitSet.Shrink();//注意此处数组Max值为10
// FruitSet == ["Fruit8", <invalid>, "Fruit6", <invalid>, "Fruit4", <invalid>, "Fruit2", <invalid>, "Fruit0" ]//CompactStable函数压缩元素,Compact函数则可能改变排序FruitSet.CompactStable();// FruitSet == ["Fruit8", "Fruit6", "Fruit4", "Fruit2", "Fruit0", <invalid>, <invalid>, <invalid>, <invalid> ]FruitSet.Shrink();// FruitSet == ["Fruit8", "Fruit6", "Fruit4", "Fruit2", "Fruit0" ]
}
相关文章:
学习虚幻C++开发日志——TSet
TSet 官方文档:虚幻引擎中的Set容器 | 虚幻引擎 5.5 文档 | Epic Developer Community (epicgames.com) TSet 是通过对元素求值的可覆盖函数,使用数据值本身作为键,而不是将数据值与独立的键相关联。 默认情况下,TSet 不支持重…...
面向对象进阶(下)(JAVA笔记第二十二期)
p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解 目录 抽象方法和抽象类抽象方法定义格式抽象类定义格式抽象方法和抽象类注意事项 接口接口的定义接口中成员变量的特点接口中没有构造方法接口中成员方法的特点在接口中定义具有方法体…...
通信协议——UART
目录 基础概念串行&并行串行的优缺点 单工&双工 UART基本概念时序图思考:接收方如何确定01和0011 基础概念 串行&并行 串行为8车道,并行为1车道 串行的优缺点 通行速度快浪费资源布线复杂线与线之间存在干扰 单工&双工 单工…...
最优阵列处理技术(七)-谱加权
阵列的加权技术等价于时间序列谱分析中的加窗或锐化技术。在加权过程中,需要考虑的是如何降低旁瓣并使主波束宽度的增长最小。 首先需要明确的是,在 u u u空间下的波束方向图为 B u ( u ) =...
Java | Leetcode Java题解之第486题预测赢家
题目: 题解: class Solution {public boolean PredictTheWinner(int[] nums) {int length nums.length;int[] dp new int[length];for (int i 0; i < length; i) {dp[i] nums[i];}for (int i length - 2; i > 0; i--) {for (int j i 1; j …...
leetcode动态规划(十五)-完全背包
题目 leetcode上没有纯完全背包题目,可以看卡码网上的题目 完全背包 思路 有N件物品和一个最多能背重量为W的背包。第i件物品的重量是weight[i],得到的价值是value[i] 。每件物品都有无限个(也就是可以放入背包多次)ÿ…...
AI视听新体验!浙大阿里提出视频到音乐生成模型MuVi:可解决语义对齐和节奏同步问题
MuVi旨在解决视频到音乐生成(V2M)中的语义对齐和节奏同步问题。 MuVi通过专门设计的视觉适配器分析视频内容,以提取上下文 和时间相关的特征,这些特征用于生成与视频的情感、主题及其节奏和节拍相匹配的音乐。MuVi在音频质量和时间同步方面表现优于现有基线方法,并展示了其在风…...
对比两个el-table,差异数据突显标记
前言 在数据分析和数据处理的过程中,经常需要对比两个数据集,以便发现其中的差异和变化。本文将介绍如何使用 el-table 组件来对比两个数据集,并通过差异数据的突显标记,帮助用户更直观地理解数据的变化。 cell-style 属性 其实利…...
调研funasr时间戳返回时间坐标效果可用性
# 背景 : 分析funasr识别结果中每个中文字的时间戳偏差情况 1.评价指标: ①偏差公式: A=标注字的时间戳(帧长区间) B=识别字的时间戳(帧长区间) 偏差=(AB的区间并集-AB的区间交际) 偏差百分比=(AB的区间并集-AB的区间交际)/(A的帧长) def calculate_bias(la…...
Tomcat默认配置整理
Connector: 处理请求的具体配置 Tomcat的连接等待队列长度,默认是100 Tomcat的最大连接数,默认是8192 Tomcat的最小工作线程数,默认是10 Tomcat的最大线程数,默认是200 Tomcat的连接超时时间,默认是20s Server port…...
深入理解Rust中的指针:裸指针 智能指针
Rust是一种注重安全性的系统编程语言,它通过所有权、借用和生命周期等机制来保证内存安全。在Rust中,指针的使用是小心翼翼的,因为指针操作是导致内存错误的主要原因之一。然而,指针在处理底层数据和性能优化时又是必不可少的。本…...
物联网实训项目:绿色家居套件
1、基本介绍 绿色家居通过物联网技术将家中的各种设备连接到一起,提供家电控制、照明控制、电话远程控制、室内外遥控、防盗报警、环境监测、暖通控制、红外转发以及可编程定时控制等多种功能和手段。绿色家居提供全方位的信息交互功能,甚至为各种能源费…...
缓存雪崩是什么
背景 Redis的缓存雪崩是指在某一时间段内,大量缓存数据同时失效,导致大量请求直接打到数据库上,造成数据库压力激增,甚至可能导致数据库宕机。这种情况类似于雪崩效应,突然的大量请求涌入数据库,系统无法承…...
【格物刊】龙信刊物已上新
文章关键词:电子数据取证、电子物证、手机取证、介质取证 深藏注册表的秘密:一次揭开金融阴谋的成功取证 一场看似无懈可击的金融操作,背后是否隐藏着阴谋?执法部门接到举报,指控几名金融机构的高层管理人员涉嫌利用…...
DNA存储介绍
1. DNA存储的基本原理 DNA存储技术基于DNA分子的双螺旋结构,利用其四种碱基(A、T、C、G)来编码信息。每个碱基可以代表一个二进制位(bit),其中A和C可以代表0,G和T可以代表1,或者使用…...
如何修改MAC地址破解网络无线网络限制-担心别人蹭网,路由器设置MAC地址过滤,限定了能访问无线网络的网卡地址-供大家学习参考
路由器都设置了MAC地址过滤,也就是限定了能访问无线网络的网卡的MAC地址。因为无线路由器不一定由自己控制,所以当更换了笔记本或者更换了无线网卡的时候,也许就上不了网了。我们可以修改网卡的MAC地址实现上网。 下载:https://do…...
C端产品经理与B端产品经理的区别
一:需求量级不一样 C端是面向消费者,吃的是人口红利,可能与社会大环境关系比较大,C端一般中大厂的需求多 B端是面向公司,吃的是产业红利,B端产品经理无论什么规模的公司都需要。 二:B端产品更…...
书生营 L0G4000 玩转HF/魔搭/魔乐社区
模型下载 在codespace上给环境装包,按照教材即可 运行后下载成功 建立下载json文件 新建下载internlm2_5-chat-1_8b的json文件 运行结果 基本上没啥问题,照着教程来就行 模型上传(可选) push的时候需要先认证token 最后的…...
轻松检测麦克风功能:使用Python的sounddevice和soundfile库
轻松检测麦克风功能:使用Python的sounddevice和soundfile库 在进行音频处理或开发需要使用麦克风的应用程序时,确保麦克风功能正常是非常重要的。本文将介绍一个简单的Python脚本,它能够帮助我们检测本地麦克风的功能,确保我们的设…...
k8s 部署步骤整理(containerd)
版本:v1.31 容器运行时:containerd 网络插件:flannel 系统:Ubuntu22.04 安装部署步骤 安装containerd sudo apt-get update sudo apt-get install ca-certificates curl sudo install -m 0755 -d /etc/apt/keyrings sudo curl …...
Swagge详解,SpringBoot项目集成Swagger
介绍 相信无论是前端还是后端开发,都或多或少地被接口文档折磨过。前端经常抱怨后端给的接口文档与实际情况不一致。后端又觉得编写及维护接口文档会耗费不少精力,经常来不及更新。其实无论是前端调用后端,还是后端调用后端,都期望…...
docker搭建etcd集群环境方式
docker搭建etcd集群环境方式 from: etcd 虚拟机与docker搭建etcd集群环境方式_docker部署etcd集群-CSDN博客 windows系统下 1: “\”要换成:“^” 2: 不能在windows powershell下执行...
重装ubuntu系统后配置
零、我的电脑硬件 1、购买型号 2021年12月25日在京东下单 7196元 联想拯救者15.6英寸 R7000P 2021游戏本 2、运行内存 内存 16 3、显卡型号 GPU nvidia RTX 3050Ti 4GB 一、安装终端 虽然自带的有,但是更方便 sudo apt install terminator 二、两个系统…...
Java基于数据库的分布式可重入锁(带等待时间和过期时间)
文章目录 技术背景介绍代码实现数据库表结构尝试获取锁续约阻塞式获取锁解锁检查锁是否过期或者释放 使用示例优化方案 项目代码 技术背景介绍 一般分布式锁使用最方便的就是使用redis实现,因为他自带超时过期机制、发布订阅模式、高吞吐高性能的优势,…...
国家信息安全水平考试(NISP一级)最新题库-第十七章
目录 另外免费为大家准备了刷题小程序和docx文档,有需要的可以私信获取 1 受到了ARP欺骗的计算机,发出的数据包, 地址是错误的() A.源IP;B.目的IP;C.源MAC;D.目的MAC 正…...
Java 8 新特性概览
Java 8 是 Java 语言发展史上的一个重要里程碑,它引入了许多革命性的特性,极大地提高了开发效率和程序性能。以下是 Java 8 的一些关键新特性: 1. Lambda 表达式 Lambda 表达式是 Java 8 中最引人注目的特性之一。它允许你以简洁的语法编写…...
pyspark==堆叠
安装环境 docker pull jupyter/all-spark-notebook 方式一 from pyspark.sql import SparkSession from pyspark.sql.functions import expr, col# 创建SparkSession spark SparkSession.builder.appName("StudentScores").getOrCreate()# 创建示例数据 data [(…...
Zypher Network Layer3 主网上线,不容错过的“宝藏方舟”活动
前言 随着 Zytron Layer3 主网的上线,Zypher Network 联合 Linea 共同推出了“宝藏方舟”活动,用户可通过参与活动,获得包括代币、积分、SBT 等系列奖励。 Zypher Network 是一个以 ZK 方案为核心的游戏底层堆栈,其提供了一个具备…...
【小白学机器学习21】 理解假设检验的关键:反证法
目录 理解假设检验的关键:反证法 1 假设的检验的出发点:H1假设, 1.1 为什么我们不去直接证明H1是否正确? 2 故意设立一个假设H1的否命题为H0 3 设定显著度α 4 总结假设检验的整个思路就是反证法 5 两类错误的关系 理解假…...
鸿蒙中富文本编辑与展示
富文本在鸿蒙系统如何展示和编辑的?在文章开头我们提出这个疑问,带着疑问来阅读这篇文章。 富文本用途可以展示图文混排的内容,在日常App 中非常常见,比如微博的发布与展示,朋友圈的发布与展示,都在使用富文…...
遵义做网站多少钱/颜色广告
解决方法 左上角file->project structure->modules->->import module->选择项目目录...
dynamo wordpress主题/南京广告宣传公司seo
传统解析html标签的方式是利用HttpWebRequest获取html字符串,然后通过正则表达式进行解析,但是这种方式比较麻烦。有没有更简单的方式呢?有,那就是Html Agility Pack,它可以做到像用XmlDocument类来解析xml一样轻松、方…...
网站收录提交入口网址/网络营销运营方案
如何让CPU的占用率曲线听你指挥写一个程序让用户来决定任务管理器的Cpu占用率。如何让CPU的占用率曲线固定在50%,保持一条直线?拿到这个问题不要着急,好好想一下。Think about it。什么是占用率?在一个Cpu的刷新周期里Cpu的使用…...
农业局网站建设方案/怎么做优化
前言 小程序开放了云开发能力,为开发者提供了一个可以很快速构建小程序后端服务的能力,作为一名对新技术不倒腾不快的前端,对此也是很感兴趣的; 而Taro 是凹凸实验室推出的,基于React 语法规范 的多端开发解决方案&a…...
皮卡剧网站怎样做/域名查询ip爱站网
这是我的服务器端代码在Java监听1880端口,并从浏览器/ client.java代码在本地主机,它给连接拒绝error.I复制该服务器代码从网页。我不知道这是什么代码在做。如何在java中监听和生成服务器端的客户端响应?import com.sun.net.httpserver.Http…...
广州专业网站制作公司/销售平台排名
例如,用户名test1改为test2,在plsql界面中不支持直接更改用户名,只能通过sql更改1、查询系统user$中的user#值select user#,name from user$ where name test1;2、根据user#值,更改用户名update user$ set nametest2 where user…...