512-不带引用计数的智能指针

我们在使用智能指针之前,一直是使用的是裸指针
在这里插入图片描述
如果我们不delete,会造成内存泄漏
或者由于中间程序的执行顺序和我们预想的不一样,导致我们资源释放的代码写了,但是没有执行到,导致内存资源泄漏
在这里插入图片描述

堆内存是我们用户手动开辟,手动释放
用不好裸指针也是造成我们内存资源非法访问,资源泄漏的一种因素

智能指针

在这里插入图片描述可以保证做到资源的自动释放
智能指针就是对普通裸指针的封装
利用栈上构造的对象出作用域自动析构的特点
在这里插入图片描述
智能指针能不能定义在堆上?
在这里插入图片描述
这样写在语法上没有问题,但是智能指针保证资源自动释放是在智能指针析构的时候。但是现在这个智能指针被放在堆上,这个指针p虽然是智能指针类型,但是它前面是星号,就不是一个对象,它就是一个普通的裸指针,所以,要让堆上的这个智能指针析构,我们首先要delete p;
使用,我们不能直接把智能指针定义在堆上,这样就没意义了。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

template<typename T>
class CSmartPtr
{
public:
	CSmartPtr(T* p = nullptr):ptr(p){}
	~CSmartPtr()
	{
		delete ptr;
	}
	T& operator*()
	{
		return *ptr;
	}
	T* operator->()
	{
		return ptr;
	}
private:
	T* ptr;
};
class Test
{
public:
	void show()
	{
		cout << "linzeyu" << endl;
	}
};
int main()
{
	CSmartPtr<int>p (new int);
	*p = 20;
	cout << *p << endl;
	CSmartPtr<Test>q(new Test());
	q->show();
	(q.operator->())->show();
}

在这里插入图片描述

不带引用计数的智能指针

我们先看下面这个例子
在这里插入图片描述
在这里插入图片描述
我们运行这段代码。

在这里插入图片描述
我们发现程序运行崩溃了。
它默认做拷贝构造的话,是浅拷贝,也就是说,在智能指针析构的时候,把同一个资源释放了2次,第2次释放就成了野指针了。

如果我们防止浅拷贝呢?
在这里插入图片描述
这样运行代码就不会崩溃了。
但是现在,p1和p2管理的是2个不同的资源,用户如果不了解的话,用户会认为他们想管理的是同一个资源。

现在,我们这个智能指针面临:怎么解决浅拷贝问题?
在这里插入图片描述
智能指针使用的使用的时候我们只需要包含头文件:
在这里插入图片描述

auto_ptr解析

在这里插入图片描述
程序崩溃了。
在这里插入图片描述

int main()
{
	auto_ptr<int>p(new int(50));
	auto_ptr<int>q(p);
	cout << *q << endl;
}

在这里插入图片描述

int main()
{
	auto_ptr<int>p(new int(50));
	auto_ptr<int>q(p);
	cout << *p<< endl;
}

在这里插入图片描述

我们转到auto_ptr的定义去看看
在这里插入图片描述
首先会调用release方法,然后把返回结果给_Myptr进行初始化

在这里插入图片描述
release做什么事情呢?
在这里插入图片描述
我们来图解release的做法如下
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
auto_ptr的成员变量只有1个裸指针,不带引用计数,它所处理的浅拷贝问题是永远只让最后一个智能指针管理资源,前面的智能指针全部置为nullptr

不推荐使用auto_ptr哦
在这里插入图片描述
容器在使用过程中,难免会做容器的拷贝构造,或者容器之间的赋值,就会引起容器每个元素的拷贝构造和赋值,如果使用智能指针auto_ptr,用vec1拷贝构造vec2,那么vec1的所有的裸指针全部被置为nullptr了。

scoped_ptr解析

比auto_ptr的浅拷贝做法还暴力。
把拷贝构造函数和赋值函数直接删除了。
在这里插入图片描述
对于scoped_ptr来说,只能使用单个对象。使用拷贝构造函数或者赋值函数,编译器就会报错。

推荐使用unique_ptr

这个智能指针也是只让1个智能指针管理资源,不会让多个智能指针管理同一个资源。
首先,unique_ptr智能指针也是先做了拷贝构造函数和赋值函数的删除。
在这里插入图片描述
但是
可以使用这样的操作
在这里插入图片描述
std::move:C++11的右值引用,std::move得到当前变量的右值类型,就是对变量进行右值引用的类型强转。

之所以可以这么实现,是因为unique_ptr提供了这样的实现:
在这里插入图片描述

在这里插入图片描述
临时对象拷贝构造ptr1

unique_ptr的好处是用户自己知道用move把资源管理权移动了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值