二、内存管理-智能指针

二、内存管理-智能指针

本文为《C++高级编程(第四版)》第七章内存管理部分,着重记录了如何使用智能指针。

智能指针是很好的管理内存的方式,并建议多使用智能指针而不是裸指针。

最简单的智能指针类型对资源有唯一所有权,当智能指针离开作用域或被重置时,会释放所引用内存,unique_ptr就是这种智能指针。

有时,多个对象或代码段包含同一个指针的多个副本。这个时候就要在使用这个资源的最后一个代码块处释放指针的资源。因此,shared_ptr就出现了,它使用“引用计数”来跟踪指针的所有者。每当复制这个智能指针的时候,都会创建一个指向同一个资源的智能指针,将引用计数加1。当一个智能指针要释放时,引用计数就会减1。当引用计数为0时,智能指针释放此资源。

头文件为<memory>

一、unique_ptr

一般要将动态分配的对象保存在堆栈的unique_ptr实例中。

1.1 创建unique_ptr

一种创建智能指针的方法就是使用automake_unique

auto test = make_unique<Test>();   // 若构造函数有参数,可以把参数放在这个括号里
test->go();    // 如果调用智能指针的方法,用.,调用智能指针指的东西的方法,用->。

如果编译器不支持此类型,还有一种。

unique_ptr<Test> test(new Test());

建议使用第一种方式创建智能指针。

1.2 使用unique_ptr

get()方法,可获取智能指针原来指向的底层指针。

cout << test.get() << endl;

可释放指针指向的对象,也可将其改成另一个指针,使用reset()

test.reset();      // 释放指向的资源,此时指针指空
test.reset(new Test());   // 释放指向的资源,指向另一个指针,先创建另一个指针,再释放此资源。

可以使用release()断开资源的连接,此方法将返回资源的底层指针,然后将智能指针置nullptr。

Test* t2 = test.release();

delete t2;

1.3 改变unique_ptr所有权

如果要将智能指针指的资源给另一个指针,由于资源唯一,先前的指针会失效,继续使用先前指针会造成不可预料的问题,并且只能使用move函数进行操作,不可直接用 = 操作。

auto test1 = make_unique<Test>();
unique_ptr<Test> test2 = move(test1);

cout << test1.get() << endl;     // 输出为0,该指针已失效,调用会造成不可预料的情况
cout << test2.get() << endl;     // 输出正确的地址

二、shared_ptr

unique_ptr一样,两种方式创建,建议使用make_shared()

使用方面略有不同,在调用reset()时,由于引用计数,仅在最后一个指针也释放了才释放资源。

2.1 建立对象的副本

有时需要将同一个对象给多个指针,这时应该使用智能指针的复制构造函数。

auto p1 = make_shared<A>();
shared_ptr<A> p2(p1);

2.2 查看资源被多少指针占有

有时候需要查看一些该资源,有多少shared_ptr占有,这时可以使用下面这个函数。

p1.use_count();

2.3 别名

试想,一个智能指针指向了一个类的对象,而另一个智能指针指向这个对象的一个属性。

class A
{
public:
    A(int num) {m_num = num;}
    int m_num;
};

int main()
{
    auto p1 = make_shared<A>(1);
    auto p2 = shared_ptr<int>(&p1->m_num);    // 1. 利用p1的属性创建智能指针
    // auto p2 = shared_ptr<int>(p1, &p1->m_num);  // 2. 利用别名构造函数
    
    return 0;
}

先看第一种创建方式,这是一种利用指针来创建指针的方式。最后p1p2都会释放自己的资源,这时会发生什么?注意,shared_ptr从来不会复制资源,资源只会有一份,shared_ptr的工作是确定什么时候去释放。

到最后p1p2都会释放资源,即资源被释放了两次,内存出错。

那如何解决这个问题呢?就是使用第二种方式,用别名构造函数。

使用别名构造函数时,p1的资源数会加1,可以使用p1.use_count()查看。也因为p1的资源数加1了,所以可以正确的释放资源。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值