auto_ptr的两种实现方式

1、旧版auto_ptr的实现方式

    最开始auto_ptr的成员变量主要有T* _ptr 和 bool _owner,主要实现原理是在构造对象时赋予其管理空间的所有权,在拷贝或赋值中转移空间的所有权,在析构函数中当_owner为true(拥有所有权)时来释放所有权。

template <class T>
class my_auto_ptr{
private:
	T* _ptr;
	bool _owner;

public:	
	my_auto_ptr(T* ptr);                               //构造函数	
	my_auto_ptr(my_auto_ptr<T>& ap);                   //复制构造函数	
	my_auto_ptr<T>& operator=(my_auto_ptr<T>& ap);     //重载赋值运算操作符
	T* operator->();                                   //重载箭头操作符
	T& operator*();                                    //重载解引用操作符	
	~my_auto_ptr();                                    //析构函数                              
};

template<class T>
my_auto_ptr<T>::my_auto_ptr(T* ptr) :_ptr(ptr), _owner(true) {}

template<class T>
my_auto_ptr<T>::my_auto_ptr(my_auto_ptr<T>& ap):_ptr(ap._ptr) {
	ap._owner = false;	
}

template<class T>
my_auto_ptr<T>& my_auto_ptr<T>::operator=(my_auto_ptr<T>& ap) {
	if (this != &ap) {
		delete this._ptr;
		this._ptr = ap._ptr;
		this._own = true;
		ap._owner = false;		
	}
	return *this;
}

template<class T>
T* my_auto_ptr<T>::operator->() {
	return this->_ptr;
}

template<class T>
T& my_auto_ptr<T>::operator*() {
	return *(this->_ptr);
}

template<class T>
my_auto_ptr<T>::~my_auto_ptr() {
	if (this->_ptr) {
		this->_owner = false;
		delete this->_ptr;
		cout << "析构了" << endl;
	}
}

    旧版auto_ptr出现的主要问题:如果拷贝出来的对象比原来的对象先出作用域或先调用析构函数,则原来的对象的_owner虽然为false,但却在访问一块已经释放的空间,原因在于拷贝对象的释放会导致原对象的_ptr指向的内容跟着被释放,这就造成指针的悬挂的问题。

int main() {
	my_auto_ptr<int> p1(new int(10));	
	cout << *p1 << endl;
	if (true) {
		my_auto_ptr<int> p2(p1);
	}	
	*p1 = 20;;
	return 0;
}

2、新版auto_ptr的实现方式

    新版auto_ptr的实现方法还是管理空间的所有权转移,但这种实现方法中没有_owner权限拥有者。构造和析构和上述实现方法类似,但拷贝和赋值后直接将_ptr赋为空,禁止其再次访问原来的内存空间,比较简单粗暴。

template<class T>
class you_auto_ptr{
public:
	you_auto_ptr(T* ptr);                                //构造函数
	you_auto_ptr(you_auto_ptr<T>& ap);                   //复制构造函数
	you_auto_ptr<T>& operator=(you_auto_ptr<T>& ap);     //重载赋值操作运算符
	T* operator->();                                     //重载箭头操作符
	T& operator*();                                      //重载解引用运算符
	~you_auto_ptr();                                     //析构函数
private:
	T* _ptr;
};

template<class T>
you_auto_ptr<T>::you_auto_ptr(T* ptr) :_ptr(ptr) {}

template<class T>
you_auto_ptr<T>::you_auto_ptr(you_auto_ptr<T>& ap):_ptr(ap._ptr) {
	ap._ptr = NULL;
}

template<class T>
you_auto_ptr<T>& you_auto_ptr<T>::operator=(you_auto_ptr<T>& ap) {
	if (this != ap) {
		delete this->_ptr;
		this->_ptr = ap._ptr;
		ap._ptr = NULL;
	}
	return *this;
}

template<class T>
T& you_auto_ptr<T>::operator*() {
	return *(this->_ptr);
}

template<class T>
T* you_auto_ptr<T>::operator->() {
	return this->_ptr;
}

template<class T>
you_auto_ptr<T>::~you_auto_ptr() {
	if (this->_ptr) {
		delete this->_ptr;
		this->_ptr = NULL;
	}
}

   这种实现方式很好的解决了旧版本野指针问题,但是由于它实现了完全的权限转移,所以导致在拷贝构造和赋值之后只有一个指针可以使用,而其他指针都置为NULL,使用很不方便,而且还很容易对NULL指针进行解引用,导致程序崩溃,其危害也是比较大的。

int main() {
	you_auto_ptr<int> p1(new int(10));	
	cout << *p1 << endl;
	you_auto_ptr<int> p2(p1);
	*p1 = 20;
	return 0;
}

auto_ptr的总结

    说了这么多,其实最终目的就是千万别用这个已经被C++摈弃的库函数,资源权限的转移带来的是安全性的问题,当你理解了它的使用带来的众多内存泄漏,程序崩溃的实例时,相信你对这个智能指针也必须保持敬畏之心了。

 参考:https://www.1024do.com/?p=2735#comments

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值