[C++]智能指针的介绍和发展

前言

之前我们学习异常的时候,面临了一个难题:存在多个可能抛出的异常时,我们需要进行多次的异常的重新抛出,比如下面这段代码:

void fxx()
{
	int* p1 = new int[10];
	int* p2, *p3;
	try
	{
		p2 = new int[20];
		try {
			p3 = new int[30];
		}
		catch (...)
		{
			delete[] p1;
			delete[] p2;
			throw;
		}
	}
	catch (...)
	{
		delete[] p1;
		throw;
	}

	//...

	delete[] p1;
	delete[] p2;
	delete[] p3;
}

这个难题,我们可以用智能指针来解决

智能指针的使用以及原理

RAII

RAII是利用对象生命周期来控制程序资源的一种技术
对象构造时获取资源,对象析构时释放资源

好处:

  • 不用显式释放资源
  • 资源在对象生命周期内始终有效

智能指针原理

**智能指针就是一个指针加上RAII。*指针可以解引用,也可
以通过->去访问所指空间中的内容,因此:我们还得需要将 、->重载下
,才可让其像指针一样去使用。

但智能指针在面临拷贝的时候,有时候会有问题:
在这里插入图片描述
下面就会简单介绍各个智能指针的发展过程

auto_ptr(通常被禁止)

最早出现的智能指针(c++98)
它的实现原理是:管理权转移
就是将被拷贝对象的资源直接转移给拷贝对象,会直接造成被拷贝对象的悬空

unique_ptr(类似scoped_ptr)

c++11对此进行了限制:禁止auto_ptr的拷贝问题
出现拷贝直接报错
用delete关键字禁掉拷贝构造和赋值就可以

shared_ptr

shared_ptr允许拷贝,并且使用引用计数来控制资源的释放
引用计数为0,释放资源

引用计数

  1. 我们有各自的引用计数可不可以
    不可以,相同的资源应该共用一个引用计数
  2. 用静态的引用计数可不可以
    不可以,静态成员属于所有对象,而当有新的对象创建时,我们应该产生新的引用计数
    我们应该一个资源配一个引用计数
  3. 我们应该 每个资源存一个指向计数的指针
  4. 赋值的注意事项
    1. 赋值之后如果计数为0,资源释放
    2. 直接的或间接的赋值给自己
    3. 解决方法:用二者的指针来判断

循环引用

循环引用是shared_ptr的一个缺陷
以双向链表为例,当我们尝试把两个节点进行连接的时候(默认这两个节点都是shared_ptr),那么我们可能写出这样的代码

bit::shared_ptr<ListNode> n1(new ListNode(10));
bit::shared_ptr<ListNode> n2(new ListNode(20));

cout << n1.use_count() << endl;
cout << n2.use_count() << endl;

n1->_next = n2;
n2->_prev = n1;

这是一个很有意思的过程,用几张图来介绍:

  1. 他们各自的情况
    在这里插入图片描述
  2. 现在的情况
    在这里插入图片描述当n1和n2析构之后,他们的引用计数都为1,资源没有释放

下面我们详细分析一下:
在这里插入图片描述
所以我们不能用循环引用

weak_ptr

c++针对循环引用给出了weak_ptr

weak_ptr不支持RAII,不支持用原生指针传参,
也就是他不增加引用计数

对于shared_ptr的补充:定制删除器

删除器默认是delete,但可以重写成delete[]之类的
并且可以结合之前的包装器的知识,进一步简化代码
具体可以看代码实现的部分

make_shared

类似make_pair,因为有人认为构建对象的时候,多次new,会生成内存碎片效率低,那么make_shared就可以让这些成员放在结构体中然后一起new

结语

对于智能指针的介绍到这里就结束了,之后会附加auto_ptr, shared_ptr, weak_ptr

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值