【UE5 C++课程系列笔记】21——弱指针的简单使用
目录
概念
声明和初始化
转换为共享指针
打破循环引用
弱指针使用警告
概念
在UE C++ 中,弱指针(TWeakPtr
)也是一种智能指针类型,主要用于解决循环引用问题以及在不需要强引用保证对象始终有效的场景下,提供一种可以获取对象访问权限的方式。与共享指针(TSharedPtr
)和共享引用(TSharedRef
)不同,弱指针不会增加其所指向对象的引用计数,这意味着它不会对对象的生命周期产生维持作用,即不会阻止对象被销毁。
例如,在一些复杂的对象关系结构中,多个对象之间可能相互引用,如果都使用强引用(如 TSharedPtr
或 TSharedRef
),很容易形成循环引用,导致对象的引用计数永远无法降为 0,从而造成内存泄漏。而弱指针可以在这种情况下参与对象的引用关系构建,避免出现循环引用问题,同时又能在对象仍然存在时,有机会获取到对象的有效访问权限。
在访问弱指针引用的对象前,应使用 Pin
函数生成共享指针。此操作确保使用该对象时其将继续存在。如只需要确定弱指针是否引用对象,可将其与 nullptr
比较,或在之上调用 IsValid
。
声明和初始化
在如下代码中,体现了弱指针不维持对象生命周期的特点,以及通过 Pin
函数检查对象是否还能获取有效访问权限的用法。
在第16行代码中,使用 MakeShared<FMyStruct>()
创建了一个 FMyStruct
类型的对象,并通过 TSharedRef
来管理这个对象,使得 ObjectOwnerRef
指向新创建的对象。此时,该对象的引用计数被初始化为 1。
第17行代码通过将 ObjectOwnerRef
作为参数传递给 TWeakPtr
的构造函数,创建了一个弱指针 ObjectObserver
,使其指向与 ObjectOwnerRef
相同的 FMyStruct
对象。需要注意的是,这个操作并不会增加对象的引用计数,对象的生命周期仍然仅由 ObjectOwnerRef
(以及后续可能出现的其他指向该对象的共享指针或共享引用)来维持,ObjectObserver
只是建立了一个对该对象的弱引用关系,用于后续在不影响对象生命周期的情况下尝试获取对对象的访问权限。
第18行代码创建了一个 TSharedPtr
类型的共享指针 ObjectOwnerPtr
,并通过赋值操作让它也指向 ObjectOwnerRef
所指向的 FMyStruct
对象。此时,对象的引用计数会从 1
(仅由 ObjectOwnerRef
维持时)变为 2。
第19行代码调用 ObjectOwnerPtr
的 Reset
函数,这会使得 ObjectOwnerPtr
释放对其所指向对象的强引用,对象的引用计数会相应地减 1
。在执行完这行代码后,对象的引用计数变回 1
,仅由 ObjectOwnerRef
来维持其生命周期。
第20~23行代码使用了 弱指针ObjectObserver
的 Pin
函数来尝试获取一个指向原对象的临时共享指针,以检查对象是否仍然可以被访问。Pin
函数会在对象仍然存在(即对应的引用计数大于 0
)的情况下,返回一个指向该对象的临时 TSharedPtr
。
转换为共享指针
Pin
函数将创建指向弱指针对象的共享指针。只要共享指针在范围内且引用对象,则该对象将持续有效。
如下代码主要展示了如何将一个由共享引用(TSharedRef
)管理的对象转换为可通过弱指针(TWeakPtr
)来间接访问的形式,并且演示了通过弱指针的 Pin
操作获取临时共享指针(TSharedPtr
),进而访问对象成员函数 PrintAA
的过程,整体体现了弱指针在不影响对象生命周期管理的情况下,实现对对象的安全访问机制。
打破循环引用
出现循环引用的示例:
首先在“FMyStruct”结构体中定义一个共享指针 HoldPtr
,并初始化为 nullptr
然后创建两个 FMyStruct
类型的对象,并通过它们各自包含的 TSharedPtr<FMyStruct>
类型成员变量 HoldPtr
互相指向对方,形成了一个循环引用的结构,如下所示。
此时调用“LoopPtr”会发现,并没有输出析构的日志信息,说明产生了循环引用现象,导致对象的引用计数永远无法降为 0。
为了打破循环引用,我们可以使用弱指针来代替共享指针
编译后运行 结果如下,可以看到对象可以正常析构了:
弱指针使用警告
如不想保证数据对象会持续存在时,弱指针将非常有用,但该属性可能会变得异常危险。在以下情况中请谨慎使用弱指针:
-
**在Set或Map中用作键。弱指针可能会在未通知容器的情况下随时无效,因此共享指针或共享引用更适用于充当键。可安全地将弱指针用作数值。
-
虽然弱指针提供
IsValid
函数,但是检查IsValid
无法保证对象在任何时间长度内均可持续有效。线程安全共享指针可能会因另一线程上的活动而随时无效,因此使用线程安全共享指针应尤其注意。Pin
返回的共享指针将使对象在代码将其清除或其超出范围前保持活跃状态,因此Pin
函数是用于检查的首选方法,此类检查会导致取消引用或访问存储对象。
官方文档地址:
https://dev.epicgames.com/documentation/zh-cn/unreal-engine/shared-references-in-unreal-engine?application_version=5.3
相关文章:

【UE5 C++课程系列笔记】21——弱指针的简单使用
目录 概念 声明和初始化 转换为共享指针 打破循环引用 弱指针使用警告 概念 在UE C 中,弱指针(TWeakPtr )也是一种智能指针类型,主要用于解决循环引用问题以及在不需要强引用保证对象始终有效的场景下,提供一种可…...

【游戏设计原理】46 - 魔杖
幻想,人们可以通过多种形式来引发,比如文字,图片,绘画,语言等,但游戏与以上这些形式的区别,正如游戏与其他艺术形式的区别一样,游戏作为一种艺术和娱乐形式,其独特之处在…...
【路径跟踪】PIDMPC
路径跟踪(Path Tracking)是指在实际行驶过程中,根据预先规划好的路径进行控制,能够沿着设定的路径行驶。常见的路径跟踪算法包括基于模型的控制方法(如PID控制器)、模型预测控制(Model Predicti…...

Spring源码分析之事件机制——观察者模式(二)
目录 获取监听器的入口方法 实际检索监听器的核心方法 监听器类型检查方法 监听器的注册过程 监听器的存储结构 过程总结 Spring源码分析之事件机制——观察者模式(一)-CSDN博客 Spring源码分析之事件机制——观察者模式(二ÿ…...

热备份路由HSRP及配置案例
✍作者:柒烨带你飞 💪格言:生活的情况越艰难,我越感到自己更坚强;我这个人走得很慢,但我从不后退。 📜系列专栏:网路安全入门系列 目录 一,HSRP的相关概念二,…...

仿生的群体智能算法总结之三(十种)
群体智能算法是一类通过模拟自然界中的群体行为来解决复杂优化问题的方法。以下是30种常见的群体智能算法,本文汇总第21-30种。接上文 : 编号 算法名称(英文) 算法名称(中文) 年份 作者 1 Ant Colony Optimization (ACO) 蚁群优化算法 1991 Marco Dorigo 2 Particle Swar…...

CentOS 7系统 OpenSSH和OpenSSL版本升级指南
文章目录 CentOS 7系统 OpenSSH和OpenSSL版本升级指南环境说明当前系统版本当前组件版本 现存安全漏洞升级目标版本升级准备工作OpenSSL升级步骤1. 下载和解压2. 编译安装3. 配置环境 OpenSSH升级步骤1. 下载和解压2. 编译安装3. 创建systemd服务配置4. 更新SSH配置文件5. 设置…...

【专题】2024年出口跨境电商促销趋势白皮书报告汇总PDF洞察(附原数据表)
原文链接:https://tecdat.cn/?p38722 在当今全球化加速演进、数字经济蓬勃发展的大背景下,跨境电商行业正以前所未有的态势重塑国际贸易格局,成为各方瞩目的焦点领域。 根据亚马逊发布的《2024年出口跨境电商促销趋势白皮书》,…...

【Ubuntu】不能连上网络
1. ping路由器的IP地址 ping 192.168.1.1 如果ping不通的话,可能是网络故障导致的。需要重启配置ip地址。配置文件 sudo vi /etc/network/interface 2. ping 8.8.8.8 如果ping不通的话,可能是路由器不能链接往外网; 或者路由器显示了当…...

CSS3 框大小
CSS3 框大小 CSS3 是网页设计和开发中不可或缺的一部分,它为开发者提供了更多样化、更灵活的样式和布局选择。在 CSS3 中,框大小(Box Sizing)是一个重要的概念,它决定了元素内容的宽度和高度以及元素整体的大小。本文将详细介绍 CSS3 框大小的概念、用法以及最佳实践。 …...

联发科MTK6771/MT6771安卓核心板规格参数介绍
MT6771,也被称为Helio P60,是联发科技(MediaTek)推出的一款中央处理器(CPU)芯片,可运行 android9.0 操作系统的 4G AI 安卓智能模块。MT6771芯片采用了12纳米工艺制造,拥有八个ARM Cortex-A73和Cortex-A53核心,主频分别…...

python中的时间模块--datetime模块、time模块
python中的时间模块 一.datetime模块二.time模块 一.datetime模块 引入时间模块 from datetime import datetime获取当前时间 print(datetime.today()) # 前的日期和时间 print(datetime.now()) # 当前的日期和时间 print(datetime.now().year) # 当前的年份 print(datetime…...

CV 处理全流程:从数据采集到模型部署的整个过程,体现全面性
CV 处理全流程:从数据采集到模型部署的整个过程,体现全面性 Numpy广播 OpenCV - Python归一化提取ROI(感兴趣区域)分离和合并通道 Pytorch 基础算子自动梯度计算 CV 全流程图像数据采集1. 确认目标2. 分析过程(使用目标-手段分析法࿰…...

OWASP ZAP之API 请求基础知识
ZAP API 提供对 ZAP 大部分核心功能的访问,例如主动扫描器和蜘蛛。ZAP API 在守护进程模式和桌面模式下默认启用。如果您使用 ZAP 桌面,则可以通过访问以下屏幕来配置 API: Tools -> Options -> API。 ZAP 需要 API 密钥才能通过 REST API 执行特定操作。必须在所有 …...

南京观海微电子----GH7009国宇测试盒使用
1. SPI接线 针对7009: 2. 国宇上位机代码准备 在主函数首尾两端加入IO2时序控制的代码、以及国语SPI有效位控制的代码(请注意7009和其他700x使用的有效位控制不一致,需要用哪一款加入哪一行即可): 三、国宇SPI读的使…...

mysql及其兼容语法数据库对于注释的特殊要求
我司大部分数据库使用MS-SQL,其中使用大量–开头的行注释,由于业务需要,切换到了Starrocks数据库(兼容mysql语法)后发现使用with开头子查询的时候,大量报错,单独执行内部的子查询又正常…...

数据去重与重复数据的高效处理策略
在实际业务中,数据去重是一个非常常见的需求,特别是在日志数据、用户操作记录或交易记录等领域。去重不仅仅是删除重复数据,更重要的是按照业务规则保留最有价值的数据记录。 本文将探讨如何在 SQL 中高效地处理重复数据,通过 DI…...

Spring Boot自动装配代码详解
概述 Spring Boot自动装配是其核心特性之一,它能够根据项目中添加的依赖自动配置Spring应用程序。通过自动装配,开发人员可以减少大量的配置工作,快速搭建起一个可用的Spring应用。 关键组件和注解 SpringBootApplication注解 这是Spring Bo…...

渗透测试-非寻常漏洞案例
声明 本文章所分享内容仅用于网络安全技术讨论,切勿用于违法途径,所有渗透都需获取授权,违者后果自行承担,与本号及作者无关,请谨记守法. 此文章不允许未经授权转发至除先知社区以外的其它平台!࿰…...

122. 买卖股票的最佳时机 II
https://leetcode.cn/problems/best-time-to-buy-and-sell-stock-ii/description/?envTypestudy-plan-v2&envIdtop-interview-150问题分析: 和买卖股票的最佳时机I这题相比,区别就是可以买多只股票虽然同时只能持有一支,但是我们还是可以…...

Python爬虫入门指南:从零开始抓取数据
Python爬虫入门指南:从零开始抓取数据 引言 在大数据时代,数据是新的石油。而爬虫作为获取数据的重要手段,受到了越来越多的关注。Python作为一门强大的编程语言,其简洁易用的特性使得它成为爬虫开发的首选语言。本篇文章将带你…...

Android使用JAVA调用JNI原生C++方法
1.native-lib.cpp为要生成so库的源码文件 2.JNI函数声明说明 NewStringUTF函数会返回jstring JNI函数声明规则 3.JAVA中声明及调用JNI函数 声明: 调用 4.源码地址: gitgithub.com:tonyimax/UpdateTimeByThread.git...

ros常用命令记录
文章目录 1.基本2.rosbag2.1录制rosbag包2.2播放录制的ROS包 3.生命周期4.ROS启动,roslaunch5.ROS消息发布6.ROS消息后台打印监控 1.基本 ros2 topic list #查看话题列表2.rosbag 2.1录制rosbag包 ros2 bag record <topic_name> #记录单个主题消息 ros2 ba…...

UE5材质节点VertexNormalWs/PixelNormalWS
VertexNormalWs顶点法线方向,此节点可以做物体上积雪、青苔等效果 PixelNormalWS像素法线方向...

友元和运算符重载
1. 友元 可以把某些选定的函数看作类的“荣誉函数”,允许它们访问类对象中非公共的成员,就好像它们是类的成员一样,这种函数称为类的友元。友元可以访问类对象的任意成员。 1.1 友元函数 友元函数是一种定义在类外部的普通函数࿰…...

【数据库事务锁的类型:读锁/写锁、悲观锁/乐观锁、表锁/页锁/行锁】
数据库事务锁的类型:读锁/写锁、悲观锁/乐观锁、表锁/页锁/行锁 一、读锁/写锁1、锁定读 二、悲观锁/乐观锁2.1 悲观锁2.2 乐观锁 三、表锁/页锁/行锁3.1 表级别的S锁、X锁3.2 表级别的意向锁(intention lock) 一、读锁/写锁 对于数据库中并…...

【Motion Builder】配置c++插件开发环境
目录 准备环境构建官方案例另行构建经验分享附录 准备环境 安装Motion Builder 2024并破解安装Qt 5.15.2 截止至2024年12月19日,Qt的在线安装器的默认页面是没有5.15.2版本的。你需要:在“选择组件”界面,选择“Archive”,点击“…...

多线程访问FFmpegFrameGrabber.start方法阻塞问题
一、背景 项目集成网络摄像头实现直播功能需要用到ffmpeg处理rtmp视频流进行web端播放 通过网上资源找到大神的springboot项目实现了rtmp视频流转为http请求进行视频中转功能,其底层利用javacv的FFmpegFrameGrabber进行拉流、推流,进而实现了视频中转。 …...

MySQL使用记录
char和varchar varchar是可变长的,实际用多少它就占多少,和char不同,char规定多少它就会占多少 varchar的长度是字符个数,不管是数字、英文还是汉字,varchar(10)都可以存10个,而不会出现因为汉字占更多的字…...

【视觉SLAM:六、视觉里程计Ⅰ:特征点法】
视觉里程计(Visual Odometry, VO)是通过处理图像序列,估计摄像头在时间上的相对位姿变化的技术。它是视觉SLAM的重要组成部分之一,主要通过提取图像中的信息(如特征点或直接像素强度)来实现相机运动估计。以…...