C++智能指针

在这里插入图片描述

RAII策略

RAII(资源获取即初始化)是一种资源管理策略,它将内存分配文件开关执行线程等操作于对象的生命周期绑定起来,确保在控制对象的生命周期结束时,按照资源获取的相反顺序释放所有资源。

什么是智能指针

智能指针就是使用了RAII策略来对堆区分配出来的空间进行管理的一些类。
这些类中分装了原生指针。

为什么要有智能指针

在这里插入图片描述
在创建堆区空间时,如果申请内存失败,而报错,则就无法到达释放test_ptr的位置,就会导致堆区内存无法被释放,导致内存泄露。

两种智能指针解析

1).unique_ptr
只能管理一份资源,及不支持拷贝构造,赋值,同时不支持隐式类型转换来构造
在这里插入图片描述
但是unique_ptr支持移动拷贝和移动赋值,但是被move的对象会被制空
在这里插入图片描述
在这里插入图片描述
在智能指针作为函数参数是,也要遵守不能拷贝构造和拷贝赋值。
在这里插入图片描述

2).shared_ptr
多个shared_ptr可以指向同时堆区空间(及支持拷贝构造,赋值),其通过引用计数来实现的,同时不支持隐式类型转换来构造
在这里插入图片描述
shared_ptr中常用的接口如下。
在这里插入图片描述
use_count()接口,返回同一个堆区资源,有多少个指针指向该资源。
在这里插入图片描述
在这里插入图片描述
unique()接口,判断某个shared_ptr指针的引用计数是否是1。
在这里插入图片描述

C++14后智能指针新接口

make_unique
该接口存在符合现代 c++ 尽量避免使用 new 来构造的原则。
在这里插入图片描述

make_shared
该接口主要有以下优点
1).比起构造,赋值等初始化shared_ptr指针,make_shared接口的性能要好。

直接使用构造,赋值初始化shared_ptr会将分配的内存块和控制块分开申请。
在这里插入图片描述
使用make_shared接口初始化shared_ptr,内存块和控制块一起申请。
在这里插入图片描述

2).异常安全
在这里插入图片描述

方法1:调用init函数,则分为三布,1.new,2.调用shared_ptr构造, 3.调用getVal函数。
如果在上述三布中,2和3调换次序,且getVal函数报错,则会导致shared_ptr没有被构造,及智能指针没有管理new出来的空间。
方法2:分为两步,1.调用make_shared函数,2.调用getVal函数。
即使次序对调,也不会产生智能指针没有管理new出来的空间的情况,要么没有被申请空间,要么申请出了空间并且被智能指针管理起来了。

weak_ptr的作用

weak_ptr的作用主要是解决shared_ptr可能导致的循环引用问题

class Parent;

class Child
{
public:
	Child()
	{
		cout << "Child" << endl;
	}
	~Child()
	{
		cout << "~Child" << endl;
	}
public:
	shared_ptr<Parent> Parent;
};


class Parent
{
public:
	Parent()
	{
		cout << "Parent" << endl;
	}
	~Parent()
	{
		cout << "~Parent" << endl;
	}
public:
	shared_ptr<Child> Child;
};


int main()
{
	shared_ptr<Child> pa(new Child());
	shared_ptr<Parent> pb(new Parent());

	pa->Parent = pb;
	pb->Child = pa;

	return 0;
}

在这里插入图片描述

其图形的内存布局如下。
在这里插入图片描述
当main函数结束后,pa,pb会被释放,则shared_ptr pa,shared_ptr pb会被释放,同时引用计数减减,会被减到1。
在这里插入图片描述
但是两个类内的指针没有被释放,但是pa,pb已经被释放了,那么这两个类就内存泄漏了。
为了解决该问题,C++提出了weak_ptr。

class Parent;

class Child
{
public:
	Child()
	{
		cout << "Child" << endl;
	}
	~Child()
	{
		cout << "~Child" << endl;
	}
public:
	weak_ptr<Parent> Parent;
};


class Parent
{
public:
	Parent()
	{
		cout << "Parent" << endl;
	}
	~Parent()
	{
		cout << "~Parent" << endl;
	}
public:
	weak_ptr<Child> Child;
};


int main()
{
	shared_ptr<Child> pa(new Child());
	shared_ptr<Parent> pb(new Parent());

	pa->Parent = pb;
	pb->Child = pa;

	return 0;
}

在这里插入图片描述
weak_ptr的特点如下。
1).weak_ptr只对资源进行监视,而不对资源进行管理,不能指向某个固定的资源,及weak_ptr不会让强引用++。
在这里插入图片描述
强引用没有++
在这里插入图片描述

2).weak_ptr只会对shared_ptr指向的资源进行管理。
3).make_shared接口会因为存在weak_ptr而导致资源释放不及时,在内存吃紧的情况下,对内存的利用率较低。
在make_shared中,内存块和资源管理块是在一起的,要释放资源管理块,需要让强引用弱引用都减到0,而如果没有使用make_shared接口,而使用new申请内存,则当强引用减到0后,就会释放内存块。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值