UE5的智能指针(UEC++个人学习笔记)

本文介绍了UnrealEngine(UE)自定义的智能指针库,包括TSharedPtr、TWeakPtr和TSharedRef,展示了如何在UE中管理内存,以及它们在避免循环引用和控制对象生命周期方面的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

核心思想:程序员只管分配堆内存,释放内存交给智能指针。UE有自己的一套内存管理系统,但这只针对与UObject。为了方便对非UObject对象的内存管理,UE设计了一套自己智能指针库。包含:共享指针(TSharedPtr)、弱指针(TWeakPtr)、以及特有的共享硬引用(TSharedRef)。

首先需要创建一个类

class TestA
{
public:
	int a = 0;
	float b = 0;
	TestA()
	{
		a = 0;
		b = 0;

	};
	TestA(int a, float b)
	{
		this->a = a;
		this->b = b;
	};
	~TestA()
	{
		UE_LOG(LogTemp, Warning, TEXT("xiguo"));
	}
private:

};

下面声明三个函数,分别用于测试不同的内容

//测试共享指针
	void TestAFunc();

	//测试共享应用
	void TestBFunc();

	//测试弱指针
	//弱指针能解决循环引用,只对引用对象保留引用权,不参与引用计
	//不能阻止对象被销毁,如果弱指针指向的对象被销毁则弱指针会自动清空
	void TestCFunc();

TestAFunc()

void AMySmartPtrActor::TestAFunc()
{
	//C++中创建指针
	TestA* ptr1 = new TestA(1, 2.0f);

	//共享指针左值初始化
	TSharedPtr<TestA>Sharedptr2(ptr1);//不推荐这种方式,容易混淆共享指针和原生指针
	ptr1 = nullptr;

	//共享指针右值初始化
	TSharedPtr<TestA>Sharedptr3(new TestA(3, 4.0f));

	//拷贝构造函数初始化
	TSharedPtr<TestA>Sharedptr4(Sharedptr2);


	//UE的方法初始化共享指针
	TSharedPtr<TestA>Sharedptr5 = nullptr;//共享指针可以初始化为空
	Sharedptr5 = MakeShareable(new TestA(5, 6.0f));

	//线程安全的共享指针
	TSharedPtr<TestA, ESPMode::ThreadSafe>Sharedptr6(new TestA(7, 8.0f));


	//共享指针常用的接口
	if (Sharedptr5.IsValid())//判断指针是否指向了一个有效的对象
	{
		TSharedRef<TestA>SharedRef1(new TestA(9,10.0f));
		//共享指针转为共享引用,引用计数加一
		SharedRef1 = Sharedptr5.ToSharedRef();

		//获得引用计数
		int32 Count1 = Sharedptr5.GetSharedReferenceCount();
		//这里为2,是MakeShareable还有SharedRef1,一共两个类对象共享同一指针
		UE_LOG(LogTemp, Warning, TEXT("Count is %d"), Count1);
		
		if (!Sharedptr5.IsUnique())
		{
			UE_LOG(LogTemp, Warning, TEXT("sharedptr5 is not Unique"));
		}
		
		//Get的作用是解引用,返回引用对象的原生指针
		Sharedptr5.Get()->a;
		UE_LOG(LogTemp, Warning, TEXT("Shareptr5a is %d"), Sharedptr5.Get()->a);

		//重置共享指针
		Sharedptr5.Reset();
		int32 Count2 = Sharedptr5.GetSharedReferenceCount();
		UE_LOG(LogTemp, Warning, TEXT("Count is %d"), Count2);
	}

}

TestBfunc()

void AMySmartPtrActor::TestBFunc()
{
	//共享引用初始化的时候必须指向一个有效的对象
	TSharedRef<TestA>SharedRef2(new TestA(7, 8.0f)); 
	if (SharedRef2.IsUnique())//
	{
		SharedRef2->a;//虽然是共享引用,但是解引用的方式仍然是->
		UE_LOG(LogTemp, Warning, TEXT("SharedRef2a is %d"), SharedRef2->a);

		TSharedPtr<TestA>Sharedptr6;

		//共享引用转换为共享指针,可以直接转化
		Sharedptr6 = SharedRef2;
		//解引用
		Sharedptr6.Get()->b;
		UE_LOG(LogTemp, Warning, TEXT("Sharedptr6b is %f"), Sharedptr6.Get()->b);
	}

}

 TestCFunc()

void AMySmartPtrActor::TestCFunc()
{
	//测试弱指针
	//弱指针能解决循环引用,只对引用对象保留引用权,不参与引用计
	//不能阻止对象被销毁,如果弱指针指向的对象被销毁则弱指针会自动清空
	TSharedPtr<TestA>Sharedptr7 = MakeShareable(new TestA(10, 11.0f));
	TSharedRef<TestA>SharedRef3(new TestA(12, 13.0f));
	//声明弱指针并初始化
	TWeakPtr<TestA>WeakPtr1(Sharedptr7);
	TWeakPtr<TestA>WeakPtr2(SharedRef3);
	if (WeakPtr1.IsValid())
	{
		//弱指针如何转换为共享指针
		TSharedPtr<TestA>Sharedptr8(WeakPtr1.Pin());
		
		if (Sharedptr8.IsValid())
		{
			Sharedptr8.Get()->a;
			UE_LOG(LogTemp, Warning, TEXT("Sharedptr8a is %d"), Sharedptr8.Get()->a);
		}
	}
}

 要记得在BeginPlay里面使用
 

void AMySmartPtrActor::BeginPlay()
{
	Super::BeginPlay();
	//TestAFunc();
	//TestBFunc();
	TestCFunc();
}

### 如何在Unreal Engine中用C++部署DeepSeek项目 #### 准备工作 为了能够在Unreal Engine (UE) 中成功部署基于C++的DeepSeek项目,开发者需先熟悉UE中的C++编程环境以及项目的构建流程[^1]。 #### 创建新项目并配置支持C++ 启动Unreal Engine编辑器后,在创建新项目时选择“Games”类别下的空白模板,并勾选“使用C++”,以便后续能够添加自定义C++代码。完成项目初始化之后,打开Visual Studio或其他IDE编译默认生成的游戏模式类文件(通常是`MyProjectNameGameModeBase.cpp/h`),确保开发工具链设置无误。 #### 导入DeepSeek资源包 假设已经获取到适用于UE版本的DeepSeek插件或源码形式的AI库,则应按照官方文档指示将其集成至当前工程内。通常情况下涉及拷贝特定目录结构下的头文件(.h),链接必要的静态/动态链接库(.lib/.dll),调整模块依赖关系等操作以满足编译需求。 #### 实现路径规划功能 对于像DeepSeek这样专注于寻路算法优化的应用来说,利用内置API `UNavigationSystem::BuildNavMeshForLevel()` 构建场景对应的导航网格显得尤为重要[^2]。此过程一般发生在关卡加载完毕后的某个时刻,比如通过覆写APlayerController派生类里的BeginPlay()方法来触发: ```cpp void ACustomPlayerController::BeginPlay() { Super::BeginPlay(); UNavigationSystemV1* NavSys = FNavigationSystem::GetCurrent<UNavigationSystemV1>(GetWorld()); if(NavSys != nullptr){ NavSys->BuildNavMeshForLevel(GetWorld()->PersistentLevel); } } ``` 上述代码片段展示了如何访问全局唯一的导航系统实例,并对其执行全地图范围内的navmesh重建任务。 #### 封装核心逻辑于独立组件之中 鉴于现代游戏引擎设计趋势倾向于面向对象程序设计理念——即尽可能多地将相似职责抽象成可重用单元;因此建议把与DeepSeek有关的数据处理、状态机转换等功能打包进专门定制化的ActorComponent子类里去[^3]。这样做不仅有助于维护清晰有序的继承层次图谱,而且便于后期调试测试阶段快速定位问题所在。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值