21 UE5 指针:智能指针 和 STL指针

2024-04-06  本文已影响0人  游戏开发程序员

STL 智能指针

unique_ptr

shared_ptr

shared_ptr 相关

weak_ptr

        // shared_ptr:记录数量是一种智能指针, 它能够记录多少个 shared_ptr 共同指向一个对象, 
        // 从而消除显示的调用 delete , 当引用计数变为零的时候就会将对象自动删除
        auto shared_pointer = make_shared<int>(10);

        // 获取原始的指针
        auto original_pointer = shared_pointer.get();

        // 查看对象的引用计数
        auto shared_pointer2 = shared_pointer;
        auto count = shared_pointer.use_count();

        // 释放 减少一个数量
        shared_pointer2.reset();

        // 全释放后 再查看原始指针数据已重置
        shared_pointer.reset();

        // unique_ptr 独占的智能指针, 它禁止其他智能指针与其共享同一个对象,从而保证代码的安全
        auto unique_pointer = make_unique<int>(20);

        // 非法获取 auto unique_pointer2 = unique_pointer;

        // 可使用move转移 转移后旧指针失效
        auto unique_pointer2 = move(unique_pointer);

        // 释放控制权,不释放内存
        auto p = unique_pointer2.release();
        *p = 21;

        // 释放内存
        unique_pointer2.reset();

        // weak_ptr 配合shared_ptr而引入,解决shared_ptr的相互引用
        // 不拥有资源的所有权,不能直接使用。无 * 和 ->
        // 通过lock获取,和expired检测是否过期。
        auto shared_p = make_shared<string>("This is shared_ptr!");

        // 不增加计数
        weak_ptr<string> weak_p = shared_p;

        // 没有过期,输出内容
        if (!weak_p.expired())
        {
            // lock()获取智能指针
            auto str = *weak_p.lock();
            *weak_p.lock() = "Change by weak_p";
            str = *weak_p.lock();
        }

        // 清空
        weak_p.reset();

UE指针关系

TSharedPtr

TSharedRef

TWeakPtr

        // TSharedPtr
        TSharedPtr<int32> MyIntSharedPtr(new int32(123));
        check(MyIntSharedPtr.IsValid()); // 有效
        check(MyIntSharedPtr.IsUnique()); // 唯一

        TSharedPtr<int32> MyIntSharedPtr2; // 可创建为空
        MyIntSharedPtr2 = MyIntSharedPtr; // 复制
        check(MyIntSharedPtr.GetSharedReferenceCount() == 2);

        const int32 DeferenceTest = *MyIntSharedPtr;
        MyIntSharedPtr.Reset(); // 重置
        check(MyIntSharedPtr.GetSharedReferenceCount() == 0);

        // checkf 调试模式下有效: 断言失败会中断程序,打印日志
        // checkf(MyIntSharedPtr.IsValid(), TEXT("MyIntSharedPtr is not Valid "));
        
        // TWeakPtr
        TSharedPtr<int32> SharedInt(new int32(64));
        TWeakPtr< int32 > WeakInt(SharedInt);
        // Pin() 返回 TSharedPtr
        check(WeakInt.Pin().IsValid());
        WeakInt.Reset(); // 重置后,就失效了
        check(!WeakInt.Pin().IsValid());

        // 绑定的智能指针重置了,也会失效
        TWeakPtr< int32 > WeakInt2(SharedInt);
        SharedInt.Reset();
        check(!WeakInt2.Pin().IsValid());

        // TSharedRef
        // 构造必须初始化 优先使用TSharedRef而不是TSharedPtr
        TSharedRef< float > FloatRef(new float(123.0f));
        const float& MyFloat = *FloatRef; // 获取内容的引用1
        const float& MyFloat2 = FloatRef.Get(); // 获取内容的引用2

        TSharedRef< float > FloatRef2 = FloatRef; // 赋值  保留了123

        FloatRef = MakeShareable(new float(456.0f));

        // 解决类内部获取自身:继承TSharedFromThis, 调用AsShared()
        // 并且声明函数标签 nodiscard : 函数的返回值应该被检查并使用.

TUniquePtr

        // TUniquePtr 带参构造函数被关键字 explicit 标记 
        TUniquePtr<int> up1(new int(1));
        // 强烈建议用MakeUnique接口 
        TUniquePtr<int> up2(MakeUnique<int>(2));
        TUniquePtr<int> up3 = MakeUnique<int>(3);

        // 拷贝/赋值重载被关键字 =delete 标记 
        // TUniquePtr<int> up4 = up1; // 编译报错 
        // TUniquePtr<int> up5(up2); // 编译报错 

        // 只能通过 MoveTemp() 转移内存所有权, 
        // 转移后up1 被析构 
        TUniquePtr<int> up6 = MoveTemp(up1);

TSharedFromeThis

        class MyClass : public TSharedFromThis<MyClass>
        {
        public:
            TSharedRef<MyClass> SharedMyself()
            {
                return SharedThis(this);
            }

            ~MyClass() 
            {
                UE_LOG(TestLog, Warning, TEXT("MyClass deleted"));
            }
        };

        // 普通指针或对象,使用TSharedFromThis内的方法会触发断言 
        TSharedPtr<MyClass> ptr = MakeShared<MyClass>();

        // 通过接口获取类实例的智能引用,维护的是同一块内存,同一个计数器 
        TSharedRef<MyClass> pRef1 = ptr->AsShared();
        TSharedRef<MyClass> pRef2 = ptr->SharedMyself();

MakeShared

MakeShareable

为什么不能用普通指针初始化智能指针

TObjectPtr介绍

上一篇下一篇

猜你喜欢

热点阅读