UE4_C++编程学习笔记-2智能指针-1unique_ptr

系列文章目录

UE4_C++编程学习笔记-1模板编程



前言

UE4中实现了自己的智能指针,在C++中原本也有自己的智能指针,本文将对两者的用法进行剖析,最重要的是通过对智能指针的用法理解,最终收获为什么UE4要这要设计智能指针。


一、为什么需要智能指针-如何养好一只猫

这里我们新建一个小猫的类,具体代码如下:

class Cat
{
public:
    Cat()
    {
        cout << "收养了一只猫" << endl;
    }
    Cat(string name)
    {
        cout << "收养了一只猫,猫名字是:" << name << endl;
        catName = name;
    }
    ~Cat()
    {
        cout << "送给别人了一只猫,猫名字是:" << catName << endl;
    }

    string GetName()
    {
        return catName;
    }
    void SetName(string myname)
    {
        catName = myname;
    }
private:
    string catName;
};

如果我们不使用智能指针,直接使用普通申请内存方式,由开发人员进行申请内存以及释放,这种方式如下:

int main()
{
    Cat* p = new Cat("原始的小嘿");
    delete p;
}

这时候程序是没有问题的,可以输入如下结果:

收养了一只猫,猫名字是:原始的小嘿
送给别人了一只猫,猫名字是:原始的小嘿

但是如果程序员比较粗心,没有写释放内存的语句,也就是delete p,那么会发生什么呢

收养了一只猫,猫名字是:原始的小嘿

可以看到,如果没有释放内存,那么只会调用类的构造函数,但是析构函数不会被调用,作为一个养猫人,当然希望只是收养而不要把猫送给别人,但是家里如果猫太多也有负担不了的一天,同样作为程序,如果只是构造而没有调用析构函数,会导致内存的泄露,更严重的就是程序的崩溃。

二、通过unique_ptr认识智能指针

1.第一个智能指针程序

从 C++ 11 开始,引入了三种智能指针unique_ptr,shared_ptr,weak_ptr。其实在C++11之前也有智能指针auto_ptr,但是已经被启用了。智能指针的程序特别简单,你只管创建指针,其他的交给智能指针。

int main()
{
    unique_ptr<Cat> u_cat_p1(new Cat("独占指针小嘿"));
}

这时候输出如下

收养了一只猫,猫名字是:独占指针小嘿
送给别人了一只猫,猫名字是:独占指针小嘿

可以看到,我们有申请内存的语句,但是没有释放内存的语句,结果依然是释放了内存调用了析构函数。这就是智能指针的魅力。

2.unique_ptr的特性-这就是你一个人的猫

unique_ptr可以用以下几种方式初始化:

int main()
{
    unique_ptr<Cat> u_cat_p1;
    Cat* p = new Cat("原始赋值给独占指针的小嘿1");
    unique_ptr<Cat> u_cat_p2(p);
    unique_ptr<Cat> u_cat_p3(new Cat("原始赋值给独占指针的小嘿2"));
}

上述程序运行后得到如下结果

收养了一只猫,猫名字是:原始赋值给独占指针的小嘿1
收养了一只猫,猫名字是:原始赋值给独占指针的小嘿2
送给别人了一只猫,猫名字是:原始赋值给独占指针的小嘿2
送给别人了一只猫,猫名字是:原始赋值给独占指针的小嘿1

如你所愿,虽然整个程序没有delete但是所有资源都在需要释放的时候被释放掉了。下面我们看看这个unique_ptr中的unique是什么意思,光从字面理解,这就是独自的意思,可以理解为,unique_ptr在同一个时段只能管理一个指针,同时被管理的指针也智能由一个unique_ptr来管理。首先我们用下面的代码来试一下:

int main()
{
    Cat* p = new Cat("原始赋值给独占指针的小嘿1");
    unique_ptr<Cat> u_cat_p1(p);
    unique_ptr<Cat> u_cat_p2(p);
}

然后我在vs中运行了一下:程序崩溃了

线程 0x8b88 已退出,返回值为 0 (0x0)。
引发了异常: 读取访问权限冲突。
**_Val** 是 0xFFFFFFFFFFFFFFFF。

所以从上面的运行结果可以看出,unique_ptr是独占的。

3.unique_ptr的释放-我不想养猫了,我想送给别人

那么如果需要释放控制权怎么做呢,就要用到release,请看下面一段代码:

int main()
{
    Cat* p = new Cat("原始赋值给独占指针的小嘿1");
    unique_ptr<Cat> u_cat_p1(p);
    u_cat_p1.release();
    cout << "u_cat_p1指针:" << u_cat_p1 << endl;
    cout << "程序执行完毕" << endl;
}

u_cat_p1在程序结束之前释放了p指针,那么p指针就需要手动释放资源,而这时没有人接管p指针了,也没有手动释放,所以运行结果如下,这里补充一点unique_ptr重载了<<输出运算符,输出自动为unique_ptr所管理的指针的地址。

收养了一只猫,猫名字是:原始赋值给独占指针的小嘿1
u_cat_p1指针:0000000000000000
程序执行完毕

release就是释放控制权的命令,那如果想释放控制权同时释放资源可以用到reset或者直接将unique_ptr置为空。代码如下:

int main()
{
    Cat* p = new Cat("原始赋值给独占指针的小嘿1");
    unique_ptr<Cat> u_cat_p1(p);
    cout << "u_cat_p1指针:" << u_cat_p1 << endl;
    u_cat_p1.reset();
    cout << "u_cat_p1指针:" << u_cat_p1 << endl;

    unique_ptr<Cat> u_cat_p2(new Cat("原始赋值给独占指针的小嘿2"));
    cout << "u_cat_p2指针:" << u_cat_p2 << endl;
    u_cat_p2 = nullptr;
    cout << "u_cat_p2指针:" << u_cat_p2 << endl;

    cout << "程序执行完毕" << endl;
}
收养了一只猫,猫名字是:原始赋值给独占指针的小嘿1
u_cat_p1指针:0000018749FC5F70
送给别人了一只猫,猫名字是:原始赋值给独占指针的小嘿1
u_cat_p1指针:0000000000000000
收养了一只猫,猫名字是:原始赋值给独占指针的小嘿2
u_cat_p2指针:0000018749FC6600
送给别人了一只猫,猫名字是:原始赋值给独占指针的小嘿2
u_cat_p2指针:0000000000000000
程序执行完毕

4.unique_ptr的转移-送给你的猫,你要养好了

如果说unique_ptr同一个时间只能控制一个指针,那么可不可以把指针转移给别人呢,答案是可以的。可以用move传递给别人。具体代码如下:

int main()
{
    Cat* p = new Cat("原始赋值给独占指针的小嘿1");
    unique_ptr<Cat> u_cat_p1(p);
    cout << "u_cat_p1指针:" << u_cat_p1 << endl;
    unique_ptr<Cat> u_cat_p2(std::move(u_cat_p1));	//p1管理的动态内存转移到p2,p1可以正常释放,但不再可用
    cout << "u_cat_p1指针:" << u_cat_p1 << endl;
    cout << "u_cat_p2指针:" << u_cat_p2 << endl;
    cout << "程序执行完毕" << endl;
}

你的猫送给别人了,别人会帮你养好的。所以运行结果如下:

收养了一只猫,猫名字是:原始赋值给独占指针的小嘿1
u_cat_p1指针:0000021A5DB87DB0
u_cat_p1指针:0000000000000000
u_cat_p2指针:0000021A5DB87DB0
程序执行完毕
送给别人了一只猫,猫名字是:原始赋值给独占指针的小嘿1

可以看到所有资源都被完美的释放了。


总结

以上就是今天要讲的内容,本文仅仅简单介绍了unique_ptr智能指针的使用,下一篇将学习共享指针最终要达到学习UE智能指针的目的。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值