手撕智能指针

目录

一、Smartptr

2、默认构造

3、有参构造

        4、拷贝构造

5、ptr1=ptr2

6、重置智能指针

7、多线程的智能指针使用演示


一、Smartptr

#pragma once
//控制块
struct countptr
{
	int ptr_count;
	countptr() :ptr_count(1) {

	}
};
template<typename T>
class Smartptr
{
private:
	T* ptr;
	countptr* control;
	void release()
	{
		if (control)
		{
			--control->ptr_count;
			if (control->ptr_count == 0)
			{
				delete ptr;
				ptr = nullptr;
				delete control;
				control = nullptr;
			}
		}
	}
public:
	Smartptr() :ptr(nullptr), control(nullptr) {

	}
	~Smartptr()
	{
		if (ptr)
		{
			release();
		}
	}
	explicit Smartptr(T* p) :ptr(p)
	{
		if (p)
		{
			control = new countptr();
		}
		else {
			control = nullptr;
		}
	}

	//拷贝构造Smartptr s2(s1)
	Smartptr(const Smartptr& s) :ptr(s.ptr), control(s.control)
	{
		if (control)
		{
			control->ptr_count++;
		}
	}

	//Smartptr s2(new student()) s2 = s1;
	Smartptr& operator = (const Smartptr& s)
	{
		if (this != &s)
		{
			release();
			ptr = s.ptr;
			control = s.control;
			if (control)
			{
				++control->ptr_count;
			}
		}
		return *this;
	}

	//移动构造
	//Smartptr s2(std::move(s1));
	//&& 表示 other 是一个右值引用,允许您在移动构造函数中接受一个临时对象
	Smartptr(Smartptr&& other) noexcept : ptr(other.ptr), control(other.control)
	{
		other.ptr = nullptr;
		other.control = nullptr;
	}
	Smartptr& operator = (const Smartptr&& other)noexcept {
		if (this != &other)
		{
			release();
			ptr = other.ptr;
			control = other.control;
			other.control = nullptr;
			other.ptr = nullptr;
		}
		return *this;
	}

	T* operator->()const
	{
		return ptr;
	}
	T& operator *()const {
		return* ptr;
	}
	T* get()const {
		return ptr;
	}
	int use_count()const {
		return control ? control->ptr_count : 0;
	}

	void reset(T* p = nullptr)
	{
		release();
		ptr = p;
		if (p)
		{
			control = new countptr();
		}
		else
		{
			control = nullptr;
		}
	}

};

2、默认构造

因为默认构造没有去绑定任何指针

Smartptr<Student>ptr1;
std::cout << "ptr1 的引用计数" << ptr1.use_count()<<std::endl;

3、有参构造

智能指针去绑定了一个裸指针

Smartptr<Student>ptr2(new Student("yds",21));
std::cout << "ptr2 的引用计数" << ptr2.use_count() << std::endl;

4、拷贝构造

通过上述代码可以看到ptr2的指针和控制块都复制给了ptr3。

两个指针共同指向同一快区域,所有ptr2和ptr3的引用计数为2

Smartptr<Student>ptr3 = ptr2;
std::cout << "ptr3 的引用计数" << ptr3.use_count() << std::endl;
std::cout << "ptr1 的引用计数" << ptr1.use_count() << std::endl;
std::cout << "ptr2 的引用计数" << ptr2.use_count() << std::endl;

5、ptr1=ptr2

将默认构造的ptr1复制上ptr2

现在三个指针共同指向一个区域

ptr1 = ptr2;
std::cout << "ptr1 的引用计数" << ptr1.use_count() << std::endl;
std::cout << "ptr2 的引用计数" << ptr2.use_count() << std::endl;
std::cout << "ptr3 的引用计数" << ptr3.use_count() << std::endl;

6、重置智能指针

  1. reset 函数会释放 ptr1 当前所指向的对象(如果有的话,前提是只有这一个指针控制该区域),并将 ptr1 指向新创建的 Student 对象。
  2. 这里 ptr1 指向新创建的 Student 对象,ptr2和pyr3共同指向的区域引用计数减1.
ptr1.reset(new Student("www",22));
std::cout << "ptr1 的引用计数" << ptr1.use_count() << std::endl;
std::cout << "ptr2 的引用计数" << ptr2.use_count() << std::endl;
std::cout << "ptr3 的引用计数" << ptr3.use_count() << std::endl;

7、多线程的智能指针使用演示

std::thread t([ptr1]() {
	ptr1->name_ = "yyy";
	std::cout << "使用线程后ptr1的引用计数" << ptr1.use_count() << std::endl;
	});
t.join();

可以看到ptr1的name被更改,且引用计数加1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值