当前位置: 首页 > news >正文

【UE4的垃圾回收】

UE4的垃圾回收

  • 1 UObjects及子类
    • 1.1 UObjects类包含UObjects成员(UPROPERTY)
    • 1.2 UObjects类包含非UObjects成员
  • 2 非UObject及子类
    • 2.1 非UObjects类包含UObjects成员1
    • 2.2 非UObjects类包含UObjects成员2
    • 2.3 非UOjbects类包含非UObjects成员
  • 3 UStructs
  • 4 容器类(TArray、TMap、TSet)
    • 4.1.当容器类存储了任意 UObjects指针
    • 4.2.当容器类存储了UObjects类外的指针
    • 4.3.UE4帮助文档摘抄

1 UObjects及子类

虚幻4引擎使用反射系统(机制)去实现垃圾回收。关于垃圾回收,你不用进行手动的去销毁你的UObjects类对象,你只需要保持对他们的引用。你的类需要继承UObject 类以支持垃圾回收。下面有个简单的例子。

UCLASS()
class MyGCType : public UObject
{GENERATED_BODY()
};

在垃圾回收器里,这里有个概念被称为 root set (根集)。根集是一个基本的对象列表,回收器不会回收根集的对象。一个对象的引用路径如果在根集里,那么它将不会被回收。如果一个对象不存在这种引用路径,称之为“unreachable”(无法访问),并且在下次垃圾回收器运行时被回收(销毁)。引擎将在一定时间间隔运行垃圾回收。

1.1 UObjects类包含UObjects成员(UPROPERTY)

本节以AActors(继承自UObjects)的一个继承类AMyActor为例说明。
Actor通常不被垃圾回收。当你在关卡中生成Actor后,如果需要在关卡卸载前销毁Actor,你需要手动的调用Destroy() 方法去销毁,但它们不会被立刻的销毁,而是在下一个垃圾回收时期被销毁。
下面是一个常见的情况,你的Actor有UObject 类型的属性。

UCLASS()
class AMyActor : public AActor
{GENERATED_BODY()public:UPROPERTY()MyGCType* SafeObject;MyGCType* DoomedObject;AMyActor(const FObjectInitializer& ObjectInitializer): Super(ObjectInitializer){SafeObject = NewObject<MyGCType>();DoomedObject = NewObject<MyGCType>();}
};void SpawnMyActor(UWorld* World, FVector Location, FRotator Rotation)
{World->SpawnActor<AMyActor>(Location, Rotation);
}

当我们调用上面的函数时,我们在世界中生成一个Actor。Actor的构造函数创建2个对象。一个被标记了UPROPERTY,另一个使用普通的指针。由于Actor本来就是根集的一部分,SafeObject 将不会被垃圾回收,因为它在根集中可以被访问。然而,DoomedObject将不会那么幸运,我们没有对它标记UPROPERTY,所以回收器将不知道它的引用,所以事实上它会被销毁。
当一个UObject 被垃圾回收,所有的UPROPERTY 类型的引用都将变成空指针。你最好在使用时检查一下是否存在空指针。

if (MyActor->SafeObject != nullptr)
{// Use SafeObject
}

正如我前面提到的,这非常的重要,Actor如果已经执行了Destroy() 方法,它将不会被移除,直到下次垃圾回收。你可以使用IsPendingKill() 方法去检查,这个UObject是否在被等待销毁。如果方法返回Ture,意味着这个UObject 已经无用了。
总结:1)UObjects对象本身已经加入回收机制;2)成员为UObjects对象时,需要UPROPERTY()以加入回收机制,否则不能加入回收机制。

1.2 UObjects类包含非UObjects成员

总结:1)UObjects对象本身已经加入回收机制;2)成员不为UObjects对象时,比如:基本数据类型(int、float)指针、结构体指针等,自行new/delete。

2 非UObject及子类

2.1 非UObjects类包含UObjects成员1

通常,非UObjects对象它能够添加一个对象引用而避免被垃圾回收。为了达到这种效果,你的类必须继承FGCObject ,并且重写AddReferencedObjects 。

class FMyNormalClass : public FGCObject
{
public:UObject* SafeObject;FMyNormalClass(UObject* Object): SafeObject(Object){}void AddReferencedObjects(FReferenceCollector& Collector) override{Collector.AddReferencedObject(SafeObject);}
};

我们使用FReferenceCollector ,为我们所需要的UObject 对象,手动添加一个硬引用,使其不能被垃圾回收。当这个对象(FMyNormalClass)被销毁并且析构函数执行,该对象将会自动清除它所添加的引用。
总结:1)非UObjects对象借助UObjects成员且继承FGCObject,同时重写AddReferencedObjects,使得非UObjects对象与UObjects成员都加入回收机制。

2.2 非UObjects类包含UObjects成员2

如果在非UObjects类中有一个UObject* A变量,那么在创建完该变量之后,最好在非UObjects类的构造函数中,使用AddToRoot,这样该变量就不会被UE4自动GC。

UObject* A = NewObject();
A->AddToRoot();

然后在非UObjects类的析构函数中,使用RemoveFromRoot即可自动让UE4GC,防止内存泄漏。

A->RemoveFromRoot();

总结:1)非UObjects对象包含的UObjects成员,通过AddToRoot和RemoveFromRoot,使得UObjects成员都加入回收机制;2)非UObjects对象,自行new/delete。

2.3 非UOjbects类包含非UObjects成员

总结:自行new/delete。

3 UStructs

UE4中提到:
“UStructs,正如前面提到,可以理解为轻量级的UObject。比如说,UStructs 不会被垃圾回收。如果你必须要用UStructs 类型的动态实例,你可能需要使用智能指针去代替,我们后面会提到。”
自己认为:
同“2 非UObject及子类”的说明。

4 容器类(TArray、TMap、TSet)

容器类一般作为类成员存在,以下按照其存储内容介绍。

4.1.当容器类存储了任意 UObjects指针

当容器类存储了任意 UObjects指针,也可被视为将UObjects对象加入垃圾回收机制,但是需要在以下两种情况中:1)当容器类作为UObjects类的成员时,需要加UPROPERTY;2)当容器类作为非UObjects类的成员时,需要非UObjects类继承FGCObject,并重写FGCObject::AddReferencedObjects()函数,与“2.1 非UObjects类包含UObjects成员1”不同的是,需要在FGCObject::AddReferencedObjects()内调用FReferenceCollector::AddReferencedObjects()函数(有多个对容器类的重载版本)。

4.2.当容器类存储了UObjects类外的指针

请自行new/delete。

4.3.UE4帮助文档摘抄

  1. 摘抄1
    UPROPERTY 或UE4容器类(例如TArray)中存储的任意 UObject 指针都被视为垃圾回收的"引用"。首先让我们从简单示例入手。
  2. 摘抄2
    TArray 添加了对其元素进行垃圾回收的好处。这样会假设 TArray 存储了 UObject 派生的指针。
UCLASS()
class UMyClass : UObject
{GENERATED_BODY();// ...UPROPERTY()AActor* GarbageCollectedActor;UPROPERTY()TArray<AActor*> GarbageCollectedArray;TArray<AActor*> AnotherGarbageCollectedArray; //从这看,不加UPROPERTY也行
};

相关文章:

【UE4的垃圾回收】

UE4的垃圾回收 1 UObjects及子类1.1 UObjects类包含UObjects成员&#xff08;UPROPERTY&#xff09;1.2 UObjects类包含非UObjects成员 2 非UObject及子类2.1 非UObjects类包含UObjects成员12.2 非UObjects类包含UObjects成员22.3 非UOjbects类包含非UObjects成员 3 UStructs4 …...

nginx负载均衡的几种配置方式介绍

一.负载均衡含义简介 二.nginx负载均衡配置方式 准备三台设备&#xff1a; 2.190均衡服务器&#xff0c;2.191web服务器1&#xff0c;2.160web服务器2&#xff0c;三台设备均安装nginx&#xff0c;两台web服务器均有网页内容 1.一般轮询负载均衡 &#xff08;1&#xff09…...

uniapp发布插件显示components/xxx文件没找到,插件格式不正确

uniapp发布插件显示components/xxx文件没找到&#xff0c;插件格式不正确 将插件文件这样一起选中&#xff0c;然后右键压缩成zip文件&#xff0c;而不是外层文件压缩...

Kubernetes(K8s)入门

一、Kubernetes是什么 Kubernetes是什么? 首先&#xff0c;它是一个全新的基于容器技术的分布式架构领先方案。这个方案虽然还很新&#xff0c;但它是谷歌十几年以来大规模应用容器技术的经验积累和升华的一个重要成果。确切地说&#xff0c;Kubernetes是谷歌严格保密十几年的…...

[前端系列第3弹]JS入门教程:从零开始学习JavaScript

本文将带领大家&#xff0c;从零开始学习JavaScript&#xff0c;fighting~ 目录 一、JavaScript简介 二、变量和数据类型 三、注释和分号 四、算术运算符 五、表达式和语句 六、代码块和作用域 七、函数&#xff08;最重要&#xff09; 一、JavaScript简介 JavaScript&…...

html 计算器界面

其他链接&#xff1a; https://www.freecodecamp.org/news/how-to-build-an-html-calculator-app-from-scratch-using-javascript-4454b8714b98/ https://codepen.io/pen/tour/welcome/start 下面展示一些 内联代码片。 <!DOCTYPE html> <html lang"en">…...

性能测试工具——LoadRunner(1)

一、LoadRunner三大组件 1.1每个组件是干什么的 VUG&#xff1a;录制脚本(编写脚本) Controller&#xff1a;设计场景&#xff0c;运行场景 Analysis&#xff1a;产生性能测试报告 1.2三大组件之间的关系 二、LoadRunner脚本录制 2.1了解WebTours系统 启动WebTours&#xf…...

安科瑞物联网表在虚拟电厂的应用

安科瑞 崔丽洁 应用场景 一般应用于控制中心 功能 能计量当前组合有功电能&#xff0c;正向有功电能&#xff0c;反向有功电能&#xff0c;正向无功电能&#xff0c;反向无功电能&#xff1b; ADW300支持RS485通讯、LORA通讯、NB、4G及Wifi通讯&#xff1b; 三套时段表,一年可以…...

XSS和CSRF

web安全策略和同源策略的意义 如果登陆了一个网站&#xff0c;不小心又打开另一个恶意网站&#xff0c;如果没有安全策略&#xff0c;则他可以对已登录的网站进行任意的dom操作、伪造接口请求等&#xff0c;因此安全策略是必要的&#xff1b; 浏览器的同源策略限制了非同源的域…...

2.物联网LWIP网络

一。创建工程 1.Cubemx创建工程 &#xff08;1&#xff09;操作系统的时钟配置 &#xff08;2&#xff09;配置ETH 注意&#xff1a;根据底板原理图&#xff0c;不是核心板原理图 &#xff08;3&#xff09;配置USART1串口&#xff0c;配置为异步通信 注意&#xff1a;配置结…...

tomcat多实例与动静分离

实验&#xff1a;在一台虚拟机上配置多台tomcat 1.配置 tomcat 环境变量 vim /etc/profile.d/tomcat.sh source /etc/profile.d/tomcat.sh 2.修改 tomcat2 中的 server.xml 文件&#xff0c;要求各 tomcat 实例配置不能有重复的端口号 vim /usr/local/tomcat/tomcat2/conf/…...

K8S下SpringCloud应用无损下线

废话不多说直接上代码&#xff0c;一种2个步骤 步骤一&#xff1a; 添加以下代码到SpringCloud应用中 import cn.hutool.extra.spring.SpringUtil; import com.alibaba.cloud.nacos.registry.NacosAutoServiceRegistration; import lombok.RequiredArgsConstructor; import lo…...

CEC2013(MATLAB):遗传算法(Genetic Algorithm,GA)求解CEC2013的28个函数

一、遗传算法GA 遗传算法&#xff08;Genetic Algorithm&#xff0c;GA&#xff09;起源于对生物系统所进行的计算机模拟研究&#xff0c;是一种随机全局搜索优化方法&#xff0c;它模拟了自然选择和遗传中发生的复制、交叉(crossover)和变异(mutation)等现象&#xff0c;从任…...

Linux tar包安装 Prometheus 和 Grafana

0. 介绍 用tar包的方式安装 Prometheus 和 Grafana Prometheus:开源的监控方案Grafana:将Prometheus的数据可视化平台 1. Prometheus 1. 下载 与 解压 官网下载: https://prometheus.io/download/#prometheus上传至机器解压命令:tar -xzf prometheus-*.tar.gz 2. 启动与暂…...

新一代分布式融合存储,数据场景All In One

1、摘要 2023年5月11日&#xff0c;浪潮信息全国巡展广州站正式启航。会上&#xff0c;重磅发布新一代分布式融合存储AS13000G7&#xff0c;其采用极致融合架构设计理念&#xff0c;实现同一套存储满足四种非结构化数据的“All In One”高效融合&#xff0c;数据存力提升300%&a…...

CGroupAndroid实践篇】三、Android CGroup控制组初始化

前面已经提到,android在init阶段,通过init trigger来触发控制组节点的创建,包括foreground,background,top-app,rt,system,dex2opt,system-background,nnapi-hal,camera-daemon,restricted等。 我们来看下android在init.rc中,是如何创建这些控制组节点的,如下:…...

lscpu的各个参数是什么意思?

$ lscpu Architecture: x86_64 #架构 CPU op-mode(s): 32-bit, 64-bit #运行方式 Byte Order: Little Endian #字节顺序 CPU(s): 96 #逻辑cpu数 On-line CPU(s) list: 0-95 #在线cpu Thread(s) per core: 2 #每个核包含线程…...

Linux学习————redis服务

目录 一、redis主从服务 一、redis主从服务概念 二、redis主从服务作用 三、缺点 四、主从复制流程 五、搭建主从服务 配置基础环境 下载epel源&#xff0c;下载redis​编辑 二、哨兵模式 一、概念 二、作用 三、缺点 四、结构 五、搭建 修改哨兵配置文件 启动服务…...

【C++手撕系列】——设计日期类实现日期计算器

【C手撕系列】——设计日期类实现日期计算器&#x1f60e; 前言&#x1f64c;C嘎嘎类中六大护法实现代码&#xff1a;获取每一个月天数的函数源码分享构造函数源码分享拷贝构造函数源码分享析构函数源码分享赋值运算符重载函数源码分享取地址和const取地址运算符重载函数源码分…...

FFmpeg常见命令行(四):FFmpeg流媒体

前言 在Android音视频开发中&#xff0c;网上知识点过于零碎&#xff0c;自学起来难度非常大&#xff0c;不过音视频大牛Jhuster提出了《Android 音视频从入门到提高 - 任务列表》&#xff0c;结合我自己的工作学习经历&#xff0c;我准备写一个音视频系列blog。本文是音视频系…...

5个核心技巧:用Pixel-Composer节点式编辑打造专业像素艺术特效

5个核心技巧&#xff1a;用Pixel-Composer节点式编辑打造专业像素艺术特效 【免费下载链接】Pixel-Composer Node base VFX editor for pixel art. 项目地址: https://gitcode.com/gh_mirrors/pi/Pixel-Composer Pixel-Composer是一款革命性的节点式像素艺术视觉特效编辑…...

AgentCode 深度技术解析:极简架构下的 AI 编程代理设计哲学

AgentCode 深度技术解析&#xff1a;极简架构下的 AI 编程代理设计哲学 一、架构设计&#xff1a;为什么"极简"反而更强大&#xff1f; 1.1 核心架构概览 AgentCode 采用经典的 ReAct&#xff08;Reasoning Acting&#xff09;范式&#xff0c;但做了关键的工程化…...

3分钟极速上手:通达信缠论量化插件完整使用指南

3分钟极速上手&#xff1a;通达信缠论量化插件完整使用指南 【免费下载链接】Indicator 通达信缠论可视化分析插件 项目地址: https://gitcode.com/gh_mirrors/ind/Indicator 在技术分析领域&#xff0c;缠论以其严谨的逻辑体系备受交易者推崇&#xff0c;但手工分析耗时…...

CubeMX配置DMAMUX的3个常见坑:以STM32H723的EXTI触发DMA为例

STM32H723 DMAMUX实战&#xff1a;EXTI触发DMA的三大陷阱与突围指南 当我们需要在STM32H7系列芯片上实现高效数据搬运时&#xff0c;DMAMUX与DMA的组合无疑是利器。但在NUCLEO-H723ZG开发板上&#xff0c;通过EXTI触发DMA传输的配置过程中&#xff0c;开发者常会遭遇几个"…...

上市公司-绿色新闻、环保新闻数据库(2007-2023年)

01、数据介绍上市公司绿色新闻报道的内容确实涵盖了多个关键方面&#xff0c;旨在向投资者、消费者、监管机构及广大公众传达企业在环境保护、可持续发展和社会责任方面的实践与成效。上市公司绿色新闻报道不仅是企业向外界传递其绿色发展成果和承诺的窗口&#xff0c;也是促进…...

如何快速实现MASA模组界面本地化:终极中文汉化实战指南

如何快速实现MASA模组界面本地化&#xff1a;终极中文汉化实战指南 【免费下载链接】masa-mods-chinese 一个masa mods的汉化资源包 项目地址: https://gitcode.com/gh_mirrors/ma/masa-mods-chinese 还在为Masa Mods复杂的英文界面而烦恼吗&#xff1f;这个专为中文玩家…...

告别黑屏!手把手教你用ZYNQ PS端库函数正确驱动VDMA,搞定OV5640实时显示

从寄存器到库函数&#xff1a;ZYNQ VDMA驱动开发的进阶实践 在ZYNQ平台上实现OV5640摄像头到LCD屏幕的实时显示&#xff0c;VDMA&#xff08;Video Direct Memory Access&#xff09;配置是关键环节。许多开发者习惯直接操作寄存器&#xff0c;这种方式直观但维护性差&#xff…...

MusicFreePlugins:打破音乐平台壁垒,打造你的专属音乐聚合器

MusicFreePlugins&#xff1a;打破音乐平台壁垒&#xff0c;打造你的专属音乐聚合器 【免费下载链接】MusicFreePlugins MusicFree播放插件 项目地址: https://gitcode.com/gh_mirrors/mu/MusicFreePlugins 还在为音乐版权限制和VIP付费墙烦恼吗&#xff1f;MusicFreePl…...

CentOS7服务器磁盘告急?别慌!手把手教你用LVM无损扩容根目录(附fdisk/lvextend/xfs_growfs全流程)

CentOS7服务器磁盘告急&#xff1f;LVM无损扩容根目录实战指南 1. 紧急状况&#xff1a;当根目录空间不足时 凌晨三点&#xff0c;监控系统突然发出刺耳的警报声——生产服务器的根目录使用率超过95%。作为运维人员&#xff0c;这种场景再熟悉不过&#xff1a;日志文件疯狂增长…...

从校园卡到智能钥匙:手把手教你用NT3H1101芯片DIY一个会发光的NFC标签(附PCB天线设计避坑指南)

从校园卡到智能钥匙&#xff1a;手把手教你用NT3H1101芯片DIY一个会发光的NFC标签&#xff08;附PCB天线设计避坑指南&#xff09; 在万物互联的时代&#xff0c;NFC技术正悄然改变着我们的生活。想象一下&#xff0c;当你把一张酷似校园卡的卡片靠近手机&#xff0c;不仅能快速…...