C++ shared_ptr实现

一、一些说明

1.智能指针用于资源管理,为了保证资源的操作得到顺利的执行防止资源泄露,因此大多数实现都以noexcept在参数列表后声明为不抛出异常。

2.对于有些明确不需要更改调用对象内容的成员函数,用const在参数列表后修饰,常量成员函数不能改变调用它的对象的内容。

3.在用原始指针构造智能指针的参数构造前用explicit声明,防止隐式的转化。

3.swap函数内部调用标准命名空间的swap()函数,必须以std::显示指定是标准命名空间

4.做笔记使用,如果有不足或者错误的地方还请补充或者指正!!多谢!!!

二、基本的构造和析构成分

SharedPtr()noexcept = default // 默认构造
explicit SharedPtr(T* ptr) noexcept // 参数构造
SharedPtr(const SharedPtr& ptr)noexcept // 拷贝构造
SharedPtr(SharedPtr&& ptr)noexcept // 移动构造
~SharedPtr() noexcept // 析构函数

三、运算符重载

SharedPtr& operator=(const SharedPtr& rhs)noexcept  // 拷贝赋值运算符重载
SharedPtr& operator=(SharedPtr&& rhs)noexcept  // 移动赋值运算符重载
T& operator->() const noexcept // 指针运算符重载
T& operator*() const noexcept // 解引用运算符重载

四、实现的shared_ptr函数接口

T* get() const noexcept // 获取原始指针对象
int use_count() const noexcept // 获取引用计数
void reset()noexcept // 重置指针
bool unique() noexcept // 判断是否只有一个使用者
void swap() noexcept // 交换对象内容

五、CPP代码

#include<iostream>
using namespace std;

// 引用计数类
class RefCount {
private:
	int count{1};
public:
	int use_count() const noexcept { return count; }
	void dec_count()noexcept { --count; }
	void inc_count()noexcept { ++count; }
};

// shared_ptr类模板
template<class T>
class SharedPtr {
private:
	T* origin_ptr{ nullptr }; // 原始指针
	RefCount* refCount{ nullptr }; // 引用计数
public:
	SharedPtr()noexcept = default; // 默认构造
	SharedPtr(nullptr_t)noexcept :SharedPtr() {} // 空指针构造
	explicit SharedPtr(T* ptr)noexcept :origin_ptr(ptr), refCount(nullptr){ // 用原始指针作为参数构造
		if (origin_ptr != nullptr) refCount = new RefCount();
	}
	SharedPtr(const SharedPtr& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 拷贝构造
		if(origin_ptr != nullptr) refCount->inc_count();
	}
	SharedPtr(SharedPtr&& ptr)noexcept :origin_ptr(ptr.origin_ptr), refCount(ptr.refCount) { // 移动构造
		ptr.origin_ptr = nullptr;
		ptr.refCount = nullptr;
	}
	~SharedPtr()noexcept { // 析构函数
		if (origin_ptr != nullptr && refCount->use_count() == 0) {
			delete origin_ptr;
			delete refCount;
			origin_ptr = nullptr;
			refCount = nullptr;
		}
	}
	SharedPtr& operator=(const SharedPtr& rhs)noexcept { // 拷贝赋值运算符重载
		SharedPtr(rhs).swap(*this);
		return *this;
	}
	SharedPtr& operator=(SharedPtr&& rhs)noexcept { // 移动赋值运算符重载
		SharedPtr(move(rhs)).swap(*this);
		return *this;
	}
	T& operator->() const noexcept{ // 指针运算符重载
		return origin_ptr;
	}
	T& operator*() const noexcept { // 解引用运算符重载
		return *origin_ptr;
	}

public: // 以下是提供的接口函数
	T* get()const noexcept { // get()函数获取原始指针对象
		return origin_ptr;
	}
	int use_count() const noexcept { // use_count()函数获取引用计数
		return origin_ptr == nullptr ? 0 : refCount->use_count();
	}
	void reset()noexcept { // reset()重置指针
		SharedPtr().swap(*this);
	}
	void reset(nullptr_t) noexcept {
		reset();
	}
	void reset(T* ptr)noexcept {
		SharedPtr(ptr).swap(*this);
	}
	bool unique()noexcept { // unique() 查看是否资源独有
		return refCount == nullptr ? false : (refCount->use_count() == 1);
	}
	void swap(SharedPtr& rhs) noexcept{ // swap()交换对象内容
		using std::swap; // 令std::swap在此函数内可用,不显示指定std中的swap版本是为了防止T专属的swap版本得不到调用
		swap(origin_ptr, rhs.origin_ptr); 
		swap(refCount, rhs.refCount);
	}
};


int main() {
	int* a = new int(2);
	SharedPtr<int>p(a); //测试构造函数
	cout << p.use_count() << endl;
	cout << *p << endl;
	SharedPtr<int>q(p); //测试拷贝构造
	cout << p.use_count() << endl;
	cout << q.use_count() << endl;
	SharedPtr<int>n = p; //测试赋值运算符
	cout << p.use_count() << endl;
	cout << n.use_count() << endl;
	SharedPtr<int>m = move(p); //测试右值引用赋值运算符
	cout << q.use_count() << endl;
	// cout << p.get_count() << endl;
	q.reset();
	cout << q.get() << endl;
	return 0;
}

 如果觉得有帮助可以三连一手哈哈哈哈,溜了溜了~~~

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
下面是一个简单的 shared_ptr 的代码实现: ```cpp template<typename T> class shared_ptr { public: shared_ptr() : ptr(nullptr), ref_count(nullptr) {} shared_ptr(T* p) : ptr(p), ref_count(new int(1)) {} shared_ptr(const shared_ptr& other) : ptr(other.ptr), ref_count(other.ref_count) { if (ref_count) { ++(*ref_count); } } shared_ptr& operator=(const shared_ptr& other) { if (this != &other) { release(); ptr = other.ptr; ref_count = other.ref_count; if (ref_count) { ++(*ref_count); } } return *this; } ~shared_ptr() { release(); } T& operator*() const { return *ptr; } T* operator->() const { return ptr; } operator bool() const { return ptr != nullptr; } T* get() const { return ptr; } private: void release() { if (ref_count) { --(*ref_count); if (*ref_count == 0) { delete ptr; delete ref_count; } ptr = nullptr; ref_count = nullptr; } } T* ptr; int* ref_count; }; ``` 在这个实现中,我们使用一个指针 `ptr` 来保存所指向的对象,使用一个指针 `ref_count` 来保存指向该对象的共享指针数量。当一个新的 shared_ptr 对象创建时,我们将 `ref_count` 初始化为 1,表示当前只有一个 shared_ptr 对象指向该对象。当我们拷贝一个 shared_ptr 对象时,我们将 `ref_count` 增加 1,并与原对象共享同一个指针。当一个 shared_ptr 对象被销毁时,我们将 `ref_count` 减 1,如果此时 `ref_count` 的值为 0,表示没有任何 shared_ptr 对象指向该对象了,我们就可以释放该对象的内存和 `ref_count` 的内存了。 此外,我们还实现了 `operator*` 和 `operator->` 来方便访问所指向的对象,实现了 `operator bool` 来判断 shared_ptr 是否为空,实现了 `get` 函数来获取指向的对象的指针。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

梦想是优秀社畜

您的打赏是对我最大的鼓励!

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

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

打赏作者

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

抵扣说明:

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

余额充值