简单实现c++中的shared_ptr及unique_ptr

练习 16.28:编写你自己版本的shared_ptr和unique_ptr.


思路:由现在在书中学到的内容,实现一个智能指针使用引用计数的方式来实现。同时并没有实现weak_ptr,因此实现智能指针是比较简单的。我在实现过程中一部分参考了std的写法,比起我之前的写法简洁了不少,但有一些特性因为不清楚std怎么实现的,不过为了追求与std的一致性,还是实现了,这一部分代码会很不自然。同时在shared_ptr实现中使用了copy and swap技术,不仅代码变得简洁了许多,同时也顺带解决了一些问题。

my_shared_ptr.h:

#ifndef MY_SHARED_PTR_H
#define MY_SHARED_PTR_H

template<typename T> class my_shared_ptr;

template<typename T>
void swap(my_shared_ptr<T> &lhs, my_shared_ptr<T> &rhs) noexcept {
	using std::swap;
	swap(lhs.ptr, rhs.ptr);
	swap(lhs.use, rhs.use);
	swap(lhs.del, rhs.del);
}

template<typename T>
class my_shared_ptr {
	friend void swap<T>(my_shared_ptr<T> &, my_shared_ptr<T> &) noexcept;
	using Deleter = std::function<void(T *)>;
public:
	my_shared_ptr() :
		ptr(nullptr), use(new unsigned int(0)) { }
	my_shared_ptr(T *);
	my_shared_ptr(nullptr_t);
	my_shared_ptr(const my_shared_ptr &rhs);
	my_shared_ptr(my_shared_ptr &&rhs)noexcept;
	my_shared_ptr(T *, const Deleter &deleter);
	my_shared_ptr(nullptr_t, const Deleter &deleter) = delete;
	my_shared_ptr(const my_shared_ptr &rhs, const Deleter &deleter);
	my_shared_ptr(my_shared_ptr &&rhs, const Deleter &deleter)noexcept;
	my_shared_ptr &operator=(my_shared_ptr)noexcept; //使用拷贝并交换技术
	explicit operator bool() const {
		return ptr != nullptr;
	}
	T &operator*() const {
		return *ptr;
	}
	T *operator->() const {
		return ptr;
	}
	T *get() const {
		return ptr;
	}
	unsigned int use_count() const {
		return *use;
	}
	bool unique() const {
		return use_count() == static_cast<unsigned int>(1);
	}
	void reset();
	void reset(T *);
	void reset(nullptr_t) = delete;
	void reset(T *, const Deleter &);
	void reset(nullptr_t, const Deleter &) = delete;
	void swap(my_shared_ptr &rhs) {
		using std::swap;
		swap(ptr, rhs.ptr);
		swap(use, rhs.use);
		swap(del, rhs.del);
	}
	~my_shared_ptr();
private:
	void try_free();
	T *ptr;
	function<void(T *)> del;
	unsigned int *use;
};

template<typename T>
my_shared_ptr<T>::my_shared_ptr(T *rhs) :
	ptr(rhs), use(new unsigned int(1)), del(nullptr) { }

template<typename T>
my_shared_ptr<T>::my_shared_ptr(nullptr_t) :
	ptr(nullptr), use(new unsigned int(0)), del(nullptr) { }

template<typename T>
my_shared_ptr<T>::my_shared_ptr(const my_shared_ptr &rhs) :
	ptr(rhs.ptr), use(rhs.use), del(rhs.del) {
	if (ptr)++ *use;
}

template<typename T>
my_shared_ptr<T>::my_shared_ptr(my_shared_ptr &&rhs) noexcept :
	ptr(rhs.ptr), use(rhs.use), del(rhs.del) {
	rhs.ptr = nullptr;
	if (ptr)++ *use;
}

template<typename T>
my_shared_ptr<T>::my_shared_ptr(T *rhs, const Deleter &deleter) :
	ptr(rhs), use(new unsigned int(1)), del(deleter) { }

template<typename T>
my_shared_ptr<T>::my_shared_ptr(const my_shared_ptr &rhs, const Deleter &deleter) :
	ptr(rhs.ptr), use(rhs.use), del(deleter) {
	if (ptr)++ *use;
}

template<typename T>
my_shared_ptr<T>::my_shared_ptr(my_shared_ptr &&rhs, const Deleter &deleter) noexcept :
	ptr(rhs.ptr), use(rhs.use), del(deleter) {
	rhs.ptr = nullptr;
	if (ptr)++ *use;
}

template<typename T>
my_shared_ptr<T> &my_shared_ptr<T>::operator=(my_shared_ptr rhs) noexcept {
	rhs.swap(*this);
	return *this;
}

template<typename T>
void my_shared_ptr<T>::reset() {
	my_shared_ptr().swap(*this);
}

template<typename T>
void my_shared_ptr<T>::reset(T *rhs) {
	my_shared_ptr(rhs).swap(*this);
}

template<typename T>
void my_shared_ptr<T>::reset(T *rhs, const Deleter &deleter) {
	my_shared_ptr(rhs, deleter).swap(*this);
}

template<typename T>
void my_shared_ptr<T>::try_free() {
	if (*use == 0) return;
	if (-- * use == 0) {
		delete use;
		use = nullptr;
		del ? del(ptr) : delete ptr;
		ptr = nullptr;
	}
}

template<typename T>
my_shared_ptr<T>::~my_shared_ptr() {
	try_free();
}

#endif

my_unique_ptr.h:

#ifndef MY_UNIQUE_PTR_H
#define MY_UNIQUE_PTR_H

template<typename T, typename D> class my_unique_ptr;

template<typename T, typename D>
void swap(my_unique_ptr<T, D> &lhs, my_unique_ptr<T, D> &rhs) {
	using std::swap;
	swap(lhs.ptr, rhs.ptr);
}

template<typename T, typename D = std::default_delete<T>>
class my_unique_ptr {
	friend void swap<T, D>(my_unique_ptr &, my_unique_ptr &);
public:
	my_unique_ptr() :
		ptr(nullptr), del(D()) { }
	my_unique_ptr(T *);
	my_unique_ptr(T *, const D &);
	my_unique_ptr(const D &);
	my_unique_ptr(my_unique_ptr &&)noexcept;
	my_unique_ptr &operator=(my_unique_ptr &&)noexcept;
	my_unique_ptr &operator=(nullptr_t)noexcept;
	T *release();
	void reset();
	void reset(T *);
	explicit operator bool() const{
		return ptr != nullptr;
	}
	T &operator*() const {
		return *ptr;
	}
	T *operator->() const {
		return ptr;
	}
	T *get() const {
		return ptr;
	}
	void swap(my_unique_ptr &lhs) {
		using std::swap;
		swap(ptr, lhs.ptr);
	}
	~my_unique_ptr();
private:
	T *ptr;
	std::function<void(T *)> del;
};

template<typename T, typename D>
my_unique_ptr<T, D>::my_unique_ptr(T *rhs) :
	ptr(rhs), del(D()) { }

template<typename T, typename D>
my_unique_ptr<T, D>::my_unique_ptr(T *rhs, const D &deleter) :
	ptr(rhs), del(deleter) { }

template<typename T, typename D>
my_unique_ptr<T, D>::my_unique_ptr(const D &deleter) :
	ptr(nullptr), del(deleter) { }

template<typename T, typename D>
my_unique_ptr<T, D>::my_unique_ptr(my_unique_ptr &&rhs) noexcept :
	ptr(rhs.ptr), del(rhs.del) {
	rhs.ptr = nullptr;
}

template<typename T, typename D>
my_unique_ptr<T, D> &my_unique_ptr<T, D>::operator=(my_unique_ptr &&rhs) noexcept {
	if (this != &rhs) {
		reset(rhs.ptr);
		rhs.ptr = nullptr;
	}
	return *this;
}

template<typename T, typename D>
my_unique_ptr<T, D> &my_unique_ptr<T, D>::operator=(nullptr_t) noexcept {
	reset();
	return *this;
}

template<typename T, typename D>
T *my_unique_ptr<T, D>::release() {
	T *ret = ptr;
	ptr = nullptr;
	return ret;
}

template<typename T, typename D>
void my_unique_ptr<T, D>::reset() {
	if (ptr) del(ptr);
	ptr = nullptr;
}

template<typename T, typename D>
void my_unique_ptr<T, D>::reset(T *rhs) {
	if (ptr) del(ptr);
	ptr = rhs;
}

template<typename T, typename D>
my_unique_ptr<T, D>::~my_unique_ptr() {
	if (ptr) del(ptr);
	ptr = nullptr;
}

#endif
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
C++,`unique_ptr`、`shared_ptr`、`weak_ptr`是三种常用的智能指针,用于管理动态分配的内存,避免内存泄漏和悬空指针等问题。 1. `unique_ptr`:是一种独占式智能指针,表示一个对象的所有权只能被一个`unique_ptr`持有,不能被其他指针或引用所共享。当`unique_ptr`超出作用域或被显式释放时,它所指向的对象将被自动销毁。例如: ```cpp std::unique_ptr<int> p(new int(10)); ``` 2. `shared_ptr`:是一种共享式智能指针,表示一个对象的所有权可以被多个`shared_ptr`共享。每个`shared_ptr`维护一个引用计数器,当引用计数器变为0时,它所指向的对象将被自动销毁。`shared_ptr`还支持自定义删除器,可以在对象销毁时执行特定的操作。例如: ```cpp std::shared_ptr<int> p = std::make_shared<int>(10); std::shared_ptr<int> q = p; ``` 3. `weak_ptr`:是一种弱引用智能指针,不能直接访问所指向的对象,只能通过调用`lock()`方法获得一个指向所指对象的`shared_ptr`。当`weak_ptr`所指向的对象已经被销毁时,`lock()`方法将返回一个空的`shared_ptr`。`weak_ptr`主要用于解决`shared_ptr`的循环引用问题,避免内存泄漏。例如: ```cpp std::shared_ptr<int> p = std::make_shared<int>(10); std::weak_ptr<int> q = p; std::shared_ptr<int> r = q.lock(); ``` 这些智能指针都定义在`<memory>`头文件,并且都是模板类,可以用于管理各种类型的动态分配内存。在实际开发,应尽量使用智能指针来管理内存,避免手动管理内存所带来的麻烦和风险。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值