news 2026/6/10 13:16:50

《Unreal 对 C++ 做了什么》系列 11. 弱引用与软引用:TWeakObjectPtr 和 TSoftObjectPtr

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
《Unreal 对 C++ 做了什么》系列 11. 弱引用与软引用:TWeakObjectPtr 和 TSoftObjectPtr

《Unreal 对 C++ 做了什么》系列 (11/54)

11. 弱引用与软引用:TWeakObjectPtr 和 TSoftObjectPtr 🔗

🚀 导言:打破“强引用”的垄断

在标准 C++ 中,std::weak_ptr必须配合std::shared_ptr。而在虚幻引擎中,所有UObject的生死由 GC 说了算。

如果我们只使用UPROPERTY标记的原始指针(强引用),会面临两个严峻问题:

  1. 循环引用(Circular Reference):两个对象互相强引用,导致 GC 永远认为它们“可达”,内存永不释放。
  2. 加载链爆炸(Reference Loading Hell):强引用会导致资源被“打包加载”。你引用了一个敌人,引擎会自动把该敌人引用的武器、特效、甚至音效全部塞进内存。

为了解决这些问题,UE 构建了TWeakObjectPtrTSoftObjectPtr


🔑 1. TWeakObjectPtr:安全的“旁观者”

TWeakObjectPtr是一种不参与 GC 追踪的弱引用。它允许你引用一个对象,但不会阻止该对象被回收。

底层黑科技:它是如何感知“死亡”的?

它内部存储的不是内存地址,而是InternalIndex(对象索引)SerialNumber(序列号)

  • 当你通过.Get()访问时,它会去全局对象表(GUObjectArray)中比对该索引下的序列号。
  • 如果序列号不匹配,说明原对象已被销毁,该指针会自动判定为nullptr。这彻底根绝了 C++ 中最恐怖的“野指针”问题。
代码实战:
// 场景:追踪一个可能会被销毁的敌人TWeakObjectPtr<AActor>EnemyWatcher;voidAMyCharacter::Track(AActor*Target){EnemyWatcher=Target;}voidAMyCharacter::Tick(floatDeltaTime){// 必须检查有效性,因为 Target 可能在上一帧被 GC 了if(EnemyWatcher.IsValid()){FVector Loc=EnemyWatcher->GetActorLocation();// 支持重载 -> 操作符}}

🔑 2. TSoftObjectPtr:内存的“节能模式”

TSoftObjectPtr底层存储的是FSoftObjectPath(资产路径字符串)。它让你的 C++ 类与庞大的资产(模型、贴图)之间实现“逻辑关联”而非“内存绑定”。

为什么需要它?

如果你在 C++ 里直接写UPROPERTY() UStaticMesh* Mesh;,那么当你加载这个 C++ 所在的类时,该模型会同步阻塞式加载。如果这种硬引用链条过长,会导致游戏启动或切换地图时出现极长的卡顿。

代码实战:异步加载范式
UPROPERTY(EditAnywhere,Category="Assets")TSoftObjectPtr<UStaticMesh>LazyMesh;voidAMyActor::StartAsyncLoad(){// 1. 检查是否已经在内存中,不在则发起异步请求if(LazyMesh.IsPending()){FStreamableManager&Manager=UAssetManager::GetStreamableManager();Manager.RequestAsyncLoad(LazyMesh.ToSoftObjectPath(),FStreamableDelegate::CreateUObject(this,&AMyActor::OnLoadComplete));}}voidAMyActor::OnLoadComplete(){// 2. 此时 Get() 才会返回真正的指针UStaticMesh*Mesh=LazyMesh.Get();MyComponent->SetStaticMesh(Mesh);}

📊 引用类型深度对比

特性强引用 (UPROPERTY*)弱引用 (TWeakObjectPtr)软引用 (TSoftObjectPtr)
底层存储原始内存地址索引 + 序列号资产路径字符串
对 GC 影响阻止对象被回收不阻止不影响(不加载就不存在)
内存成本高(强制对象驻留内存)极低极低
访问速度极快(直接访问)中(需要一次索引比对)慢(首次访问需加载)
自动置空是(GC 时自动设为 null)是(IsValid 返回 false)否(需手动检查)

🛠️ 实战建议:什么时候该选谁?

  • 父子关系:如果 A 拥有 B(比如角色拥有武器组件),使用强引用
  • 观察关系:如果 A 只是临时关注 B(比如 AI 寻找目标、UI 显示当前选中的对象),使用弱引用
  • 资源配置:对于在编辑器里由策划配置的皮肤、关卡道具、UI 图标,使用软引用
  • 循环引用:如果你发现两个 UObject 互相需要对方的指针,请将其中一方改为弱引用

⚠️ 性能警告

TWeakObjectPtr虽然安全,但它的.Get()操作比原生指针稍慢(存在查表开销)。请避免在Tick函数中对数千个弱引用执行Get()操作,如有必要,请在循环外缓存为本地原生指针。


下一篇预告:《12. UObject 生命周期重载:PostInit, PostLoad, BeginDestroy》

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/9 23:42:04

大模型学习路线图:从小白到AI专家的成长之路_【2026最新】大模型AI产品经理学习路线

文章提供了大模型产品经理从零基础到精通的完整学习路线&#xff0c;涵盖基础知识、大模型技术、产品管理、实战经验和持续学习五大阶段。同时介绍了大模型在教育、医疗、金融等领域的应用场景&#xff0c;并提供了学习资源获取方式。这条系统性学习路径旨在帮助读者掌握大模型…

作者头像 李华
网站建设 2026/6/10 11:39:33

系统软件出现msvcp140.dll文件找不到 如何修复? 免费下载方法分享

在使用电脑系统时经常会出现丢失找不到某些文件的情况&#xff0c;由于很多常用软件都是采用 Microsoft Visual Studio 编写的&#xff0c;所以这类软件的运行需要依赖微软Visual C运行库&#xff0c;比如像 QQ、迅雷、Adobe 软件等等&#xff0c;如果没有安装VC运行库或者安装…

作者头像 李华
网站建设 2026/6/10 11:38:48

paperxie 毕业论文写作工具:解锁高效学术创作的智能密钥

paperxie-免费查重复率aigc检测/开题报告/毕业论文/智能排版/文献综述/aippt https://www.paperxie.cn/ai/dissertationhttps://www.paperxie.cn/ai/dissertation 在学术评价体系日趋严格的当下&#xff0c;毕业论文不仅是学生学业生涯的收官之作&#xff0c;更是衡量其科研能…

作者头像 李华
网站建设 2026/6/10 10:46:46

Android16 设置AP热点不自动关闭和热点默认设置5G

1.让ap热点不自动关闭: packages/modules/Wifi/service/ServiceWifiResources/res/values/config.xml <integer translatable="false" name="config_wifiFrameworkSoftApShutDownTimeoutMilliseconds">600000</integer> 修改为: <int…

作者头像 李华
网站建设 2026/6/10 0:34:14

AI agents协作分析社交网络:评估公司的社会影响力

AI agents协作分析社交网络&#xff1a;评估公司的社会影响力关键词&#xff1a;AI agents、社交网络分析、公司社会影响力评估、协作机制、数据挖掘摘要&#xff1a;本文聚焦于利用AI agents协作分析社交网络来评估公司的社会影响力。首先介绍了研究背景、目的和预期读者等内容…

作者头像 李华