UE4/5 插件分拆 《第一季》运行时地形07轮子篇 浅挖一下UE的智能指针

本文探讨了为什么UE4和UE5选择自定义智能指针而不是使用std::shared_ptr,并详细分析了UE智能指针的线程安全模式、SharedPointerInternal的实现以及TSharedFromThis的角色。通过深入源码,揭示了UE智能指针在线程安全、性能优化和类型转换方面的设计考虑。
摘要由CSDN通过智能技术生成

#include "VoxelSharedPtr.h"

/Engine/Source/Runtime/Core/Public/Templates/SharedPointer.h 里面有UE智能指针详细用法,还有解释了为什么要自己造轮子

/*    Why did we write our own Unreal shared pointer instead of using available alternatives?
 *
 *        - std::shared_ptr (and even tr1::shared_ptr) is not yet available on all platforms
 *        - Allows for a more consistent implementation on all compilers and platforms
 *        - Can work seamlessly with other Unreal containers and types
 *        - Better control over platform specifics, including threading and optimizations
 *        - We want thread-safety features to be optional (for performance)
 *        - We've added our own improvements (MakeShareable, assign to nullptr, etc.)
 *        - Exceptions were not needed nor desired in our implementation
 *        - We wanted more control over performance (inlining, memory, use of virtuals, etc.)
 *        - Potentially easier to debug (liberal code comments, etc.)
 *        - Prefer not to introduce new third party dependencies when not needed
 */

ESPMode::ThreadSafe 相对于 ESPMode::NotThreadSafe 和自动平台适应 ESPMode::Fast 
C++标准库的 std::shared_ptr 只是引用计数安全,  这难免让我对SharedPointer源码有了一点期待

//VoxelSharedPtr.h
template<typename T>
using TVoxelSharedRef = TSharedRef<T, ESPMode::ThreadSafe>; 

我们顺着插件这条到SharedPointerInternal.h挖一下得到

//SharedPointerInternal.h
template< class ObjectType, ESPMode Mode = ESPMode::Fast > class TSharedRef;
template< class ObjectType, ESPMode Mode = ESPMode::Fast > class TSharedPtr;
template< class ObjectType, ESPMode Mode = ESPMode::Fast > class TWeakPtr;
template< class ObjectType, ESPMode Mode = ESPMode::Fast > class TSharedFromThis;

表明UE4和UE5的智能指针默认就算不安全的
然后继续挖回到SharedPointer.h看到

//SharedPointer.h
template< class ObjectType, ESPMode Mode >
class TSharedRef
{
public:
	using ElementType = ObjectType;

	// NOTE: TSharedRef has no default constructor as it does not support empty references.  You must
	//		 initialize your TSharedRef to a valid object at construction time.

	/**
	 * Constructs a shared reference that owns the specified object.  Must not be nullptr.
	 *
	 * @param  InObject  Object this shared reference to retain a reference to
	 */
	template <
		typename OtherType,
		typename = decltype(ImplicitConv<ObjectType*>((OtherType*)nullptr))
	>
	FORCEINLINE explicit TSharedRef( OtherType* InObject )
		: Object( InObject )
		, SharedReferenceCount( SharedPointerInternals::NewDefaultReferenceController( InObject ) )
	{
		UE_TSHAREDPTR_STATIC_ASSERT_VALID_MODE(ObjectType, Mode)

		Init(InObject);
	}
	
	private:

	/** The object we're holding a reference to.  Can be nullptr. */
	ObjectType* Object;

	/** Interface to the reference counter for this object.  Note that the actual reference
		controller object is shared by all shared and weak pointers that refer to the object */
	SharedPointerInternals::FSharedReferencer< Mode > SharedReferenceCount;
}

然后再顺着ESPMode挖得到

// TSharedPtr of one mode to a type which has a TSharedFromThis only of another mode is illegal.
// A type which does not inherit TSharedFromThis at all is ok.
// We only check this inside the constructor because we don't necessarily have the full type of T when we declare a TSharedPtr<T>.
#define UE_TSHAREDPTR_STATIC_ASSERT_VALID_MODE(ObjectType, Mode) \
	enum \
	{ \
		ObjectTypeHasSameModeSharedFromThis = TPointerIsConvertibleFromTo<ObjectType, TSharedFromThis<ObjectType, Mode>>::Value, \
		ObjectTypeHasOppositeModeSharedFromThis = TPointerIsConvertibleFromTo<ObjectType, TSharedFromThis<ObjectType, (Mode == ESPMode::NotThreadSafe) ? ESPMode::ThreadSafe : ESPMode::NotThreadSafe>>::Value \
	}; \
	static_assert(ObjectTypeHasSameModeSharedFromThis || !ObjectTypeHasOppositeModeSharedFromThis, "You cannot use a TSharedPtr of one mode with a type which inherits TSharedFromThis of another mode.");

这里判断class如果是TSharedFromThis 的继承类就不能修改线程安全状态
我的初步理解是, 这样会报错, 但问题是判断过程, 应该是编译器负责的, 我很好奇,最后讲讲

//Fake Code
#include "CoreMinimal.h"
class SomeClass:TSharedFromThis<OwnClass, ESPMode::
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值