虚幻智能指针库

本页面的内容:

智能指针

虚幻智能指针库 是共享引用(TSharedRef)、共享指针 (TSharedPtr)、弱指针(TWeakPtr)及其他相关辅助函数及类的自定义实现。 该实现是根据 C++0x 标准库的 shared_ptr 和 Boost 的智能指针建模的。

类型 描述
共享指针 (TSharedPtr) 引用计数的非侵入式的权威智能指针。
共享引用 (TSharedRef) 不能设置为null值的、引用计数的、非侵入式权威智能指针。
弱指针 (TWeakPtr) 引用计数的、非侵入式弱指针引用。

共享引用和共享指针的优点

优点 描述
简洁的语法 您可以像操作常规的C++指针那样来复制、解引用及比较共享指针。
防止内存泄露 当没有共享引用时资源自动销毁。
弱引用 弱指针允许您安全地检查一个对象是否已经被销毁。
线程安全 包含了可以通过多个线程安全地进行访问的"线程安全"版本。
普遍性 您几乎可以创建到 任何 类型的对象的共享指针。
运行时安全 共享引用永远不会为null,且总是可以进行解引用。
不会产生引用循环 使用弱引用来断开引用循环。
表明用途 您可以轻松地区分对象 拥有者观察者
性能 共享指针的性能消耗最小。 所有操作所占时间都是固定的。
强大的功能 支持针'const'、前置声明的不完全类型、类型转换等。
内存 所占内存大小是C++指针在64-位系统中所占内存的二倍 (外加了一个共享的16字节的引用控制器。)

创建自定义库的原因

辅助类和函数

在库中,以类和函数的形式提供了几个辅助功能,以便使得应用智能指针变得更加容易、更加直观。

辅助功能 描述

TSharedFromThis 您可以让您自己的类继承这个类,来从“this”获得而一个TSharedRef 。

函数

MakeShareable() 用于通过C++指针初始化共享指针(启用隐式转换) 。
StaticCastSharedRef() 静态类型转换效用函数,一般用于向下类型转换为派生类型。
ConstCastSharedRef() 将一个'const(常量的)'引用转换为'mutable(可变的)'智能引用。
DynamicCastSharedRef() 动态类型转换效用函数,一般用于向下类型转换为派生类型。
StaticCastSharedPtr() 静态类型转换效用函数,一般用于向下类型转换为派生类型。
ConstCastSharedPtr() 将一个'const(常量的)'引用转换为'mutable(可变的)'智能指针。
DynamicCastSharedPtr() 动态类型转换效用函数,一般用于向下类型转换为派生类型。

智能指针实现细节

虚幻智能指针库中的各种智能指针类型的实现在性能、内存等方面都具有一些共有的特性。

性能

当考虑使用共享指针时要时刻记住性能问题。共享指针的执行速度一般是非常快的;然而,这并不意味着任何地方都使用它。它们非常适用于某些高层系统或者工具编程,但不是很适合底层的引擎/路径渲染。

共享指针的在性能方面的一些优势有:

共享指针在性能方面的劣势包括:

内存使用量

所有的共享指针 (TSharedPtr, TSharedRef, TWeakPtr)都占8个字节(当针对32-位系统编译时),包括:

TSharedFromThis 也占8个字节,因为它内嵌了弱指针。

引用控制器对象占12个字节(当针对32-位系统编译时),包括:

无论有多少个 共享指针/弱指针 引用一个对象,都仅为每个对象创建一个引用控制器。

反射

共享指针是非侵入式的,这意味着该类本身不知道它是否属于另一个共享指针(或引用)。一般,这是可以的,但有时候您想把当前实例作为共享引用访问。这种情况的解决方法是让该类继承于 TSharedFromThis<>

通过继承 TSharedFromThis<> ,您可以使用 AsSharedRef() 方法来将'this'转换为一个共享引用。 这对于总是返回共享引用的类工厂是非常有用的。

class FAnimation : public TSharedFromThis<FMyClass>
{
    void Register()
    {
        // Access a shared reference to 'this'
        TSharedRef<FMyClass> SharedThis = AsSharedRef();

        // Class a function that is expecting a shared reference
        AnimationSystem::RegisterAnimation( SharedThis );
    }
}

类型转换

您可以轻松地对共享指针(及引用)进行类型转换。和C++中的指针一样,向上类型转换是隐式的。

针对常量型指针进行类型转换(很不好,但有时候需要这样做):

ConstCastSharedPtr<T>( ... )

静态类型转换(通常用于向下类型转换为派生类指针):

StaticCastSharedPtr<T>( ... )

不支持动态类型转换(没有运行时类型信息)。 此时,您可以使用上面的静态类型转换。

线程安全性

常规的共享指针仅在单线程上访问是安全的。如果您需要多线程访问共享指针,那么请使用指针类的线程安全版本:

由于这些版本存在自动引用计数,所以运行速度略慢,但其行为和常规的C++指针几乎一样。

如果您知道永远不会有多个线程访问您的指针,那么请不要使用线程安全版本。

应用详情

SharedPointerTesting.h 文件 (位于 [UE4RootLocation]/Engine/Source/Runtime/Core/Public/Templates/) 包含了使用共享指针和共享引用的各种示例。

技巧

限制

和其他实现的区别