从零完成智能指针

        写C/C++程序常常苦恼于内存的释放管理,需要程序开发人员自己去管理,拥有内存控制权限的同时也带来了很多头疼的释放操作,从而导致内存的泄露。那到底有哪些“不正规”操作导致了内存泄漏呢:

  1. new了一个对象忘记delete的
  2. delete后忘记将指针置为NULL的
  3. 异常或者中断(程序退出)发生在delete之前的

       可见new delete需要耗费程序开发人员不少心思去细致的处理,实在是繁琐,因此,智能指针应运而生。智能指针在C++11中引入,实现了动态内存管理。其shared_ptr采用引用计数的方式管理所指向的对象。当有一个新的shared_ptr指向同一个对象时(复制shared_ptr等),引用计数加1。当shared_ptr离开作用域时,引用计数减1。当引用计数为0时,释放所管理的内存。这样做的好处在于缓解了程序员手动释放内存的压力。之前,为了处理程序中的异常情况,往往需要将指针手动封装到类中,通过析构函数来释放动态分配的内存;现在这一过程就可以交给shared_ptr去做了。

        最近阅读安卓源码,发现其底层C++代码就封装了智能指针,因此我们今天就自己实现一下智能指针,当做轮子。

       1.大致框架

        按照标准类的定义,我们来实现一个动态模板类的雏形-----sp(smart ptr)。

template<typename T>
class sp {
public:
	//----------------------------------------
	sp():ptr(nullptr){}
	sp(T* other);
	sp(const sp<T>& other);

	~sp();

private:
	T* ptr;
	int* use_count;
};

template<typename T>
sp<T>::sp(T * other):ptr(other)
{
	use_count = new int(1);
}

template<typename T>
sp<T>::sp(const sp<T>& other)
{
	ptr = other.ptr;
	use_count = other.use_count;
	++(*use_count);
}

template<typename T>
sp<T>::~sp()
{
	if (--(*use_count) == 0) {
		delete ptr;
		delete use_count;
		ptr = nullptr;
		use_count = nullptr;
	}
}

        2.添加常用操作。

       仔细分析一下,这样显然是满足不了日常需求的。

  •        此模式下传参只能传T*类型的,显然不满足类型转换的需求
  •        没有常用的操作运算符,需要优化
  •        指针提取和解引用太过麻烦

       因此我们可以做出适当优化,下面给出程序:

#define COMPARE(_op_)                                                                                                   
template<typename U>                                            \
inline bool operator _op_ (const sp<U>& o) const {              \
    return m_ptr _op_ o.m_ptr;                                  \
}                                                               \
template<typename U>                                            \
inline bool operator _op_ (const U* o) const {                  \
    return m_ptr _op_ o;                                        \
}                                                               \
template <typename T>
class sp {
public:
	//----------------------------------------
	sp():m_ptr(nullptr){}
	template<typename U> sp(U* other);  // NOLINT, implicit
	template<typename U> sp(const sp<U>& other);  // NOLINT, implicit
	~sp();

	template<typename U> sp& operator = (const sp<U>& other);
	template<typename U> sp& operator = (U* other);

	// Accessors
	inline  T&      operator * () const { return *m_ptr; }
	inline  T*      operator -> () const { return m_ptr; }
	inline  T*      get() const { return m_ptr; }

	// Operators
	COMPARE(== )
	COMPARE(!= )
	COMPARE(> )
	COMPARE(< )
	COMPARE(<= )
	COMPARE(>= )
private:
	T* m_ptr;
	int* use_count;
};
template<typename T> template<typename U>
sp<T>::sp(U* other) : m_ptr(other)
{
	if (m_ptr) {
		use_count = new int(1);
		cout << "P constructor called. " <<*use_count<< endl;
	}
}
template<typename T> template<typename U>
sp<T>::sp(const sp<U>& other)
	: m_ptr(other.m_ptr)
{
	if (m_ptr) {
		use_count = other.use_count;
		++(*use_count);
		cout << "SP constructor called. " <<*use_count<< endl;
	}
}
template<typename T>
sp<T>::~sp()
{
	if (--(*use_count) == 0) {
		cout << "Destructor called."<<endl;
		delete m_ptr;
		delete use_count;
		m_ptr = nullptr;
		use_count = nullptr;
	}
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (const sp<U>& other) {
	cout << "SP copy called." << endl;
	++(*other.use_count);
	if (--(*use_count) == 0) {
		delete m_ptr;
		delete use_count;
	}
	m_ptr = other.m_ptr;
	use_count = other.use_count;
	return *this;
}
template<typename T> template<typename U>
sp<T>& sp<T>::operator = (U* other)
{
	cout << "P copy called."<<endl;
	if (--(*use_count) == 0) {
		delete m_ptr;
		delete use_count;
	}
	m_ptr = other;
	*use_count = 1;
	return *this;
}

          还有一些运算符没有重载,天色已完,改日再叙。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值