码迷,mamicode.com
首页 > 编程语言 > 详细

C++_智能指针

时间:2016-04-07 01:42:40      阅读:197      评论:0      收藏:0      [点我收藏+]

标签:智能指针 raii

讲这个之前,先来看一个例子:

void Test1 ()
{
    int* p1 = new int(2);
    //...
    try 
    {   
      DoSomeThing();
    }
    catch(...)
    {
      delete p1 ;
      throw;
    }
    //...
    delete p1 ;
}

这个例子,是通过C++异常处理机制,来管理动态开辟出来的内存,这是可以做到的。那如果我们以后new出来一块内存,都要这么做,那么代码量将会相当的大,有时候逻辑也会理不清楚,也显得非常繁琐,那C++为了处理这个问题,提出了一个叫RAII(Resource Acquisition Is Initialization)的东东。


RAII资源分配即初始化,定义一个类来封装资源的分配和释放,在构造函数完成资源的分配和初始化,在析构函数完成资源的清理,可以保证资源的正确初始化和释放。这个类具体到下面的智能指针。

智能指针:所谓智能指针就是智能\自动化管理动态开辟内存的释放。

在C++11之前,标准库中,只有一个auto_ptr,下面是模拟实现auto_ptr旧版本.

/*旧版本*/

/*实现原理:通过拥有者的改变来最后确定是否析构对象*/

#include <iostream>

using namespace std;

template<class T>
class AutoPtr
{
public:
	AutoPtr(T* ptr)
		:_ptr(ptr)
	{
		_owner = true;
	}
	AutoPtr(AutoPtr<T>& ap)
		:_ptr(ap._ptr),_owner(ap._owner)
	{
		ap._owner = false;
	}
	AutoPtr<T>& operator=(AutoPtr<T>& ap)
	{
		if(this != &ap)
		{
			if(_owner)
			{
				delete _ptr;
			}
			_ptr = ap._ptr;
			_owner = ap._owner;
			if(ap._owner)
			{
				ap._owner = false;
			} 
		}
		return *this;
	}
	~AutoPtr()
	{
		if(_owner)
		{
			delete _ptr;
		}
	}
public:
	T& operator*()
	{
		return *_str;
	}
	T* operator ->()
	{
		return _str;
	}
private:
	T* _ptr;
	bool _owner;
};
void Test1()
{
	AutoPtr<int> ap1(new int(1));
	AutoPtr<int> ap2(ap1);
	AutoPtr<int> ap3(new int(3));
	ap3 = ap2;
}
int main()
{
	Test1();
	return 0;
}

显示结果:

技术分享

这样看结果是对的,但是看下面这个Test2()

void Test2()
{
	AutoPtr<int> ap1(new int(1));
	AutoPtr<int> ap2(ap1);
	AutoPtr<int> ap3(new int(3));
	AutoPtr<int> ap4(ap3);
	ap4 = ap1;
}

显示结果:

技术分享

看上面就出现问题了,你把ap1 赋给 ap4 ,但是ap4的_owner 是 false ,这就是有问题的。到最后,ap4只是指向共有的那块空间而已,没有达到真正的管理,再看Test3()

void Test3()
{
	AutoPtr<int> ap1(new int(1));
	if(1)
	{
		AutoPtr<int> ap2(ap1);
	}
	*ap1 = 10;
}

显示结果:

技术分享

程序直接崩溃了,因为产生了野指针的访问,访问的那一块空间已经释放了,所以就会崩溃了,正是由于旧版本有这诸多的问题,C++改进了一下他,使他变得很“强大”,下来看模拟实现:

/*新版本*/

/*实现原理:管理权的转交*/

#include <iostream>
using namespace std;
 
template <class T>
class AutoPtr
{
public:
	AutoPtr(T* str)
		:_str(str)
	{}
	AutoPtr(AutoPtr<T>& ap)
		:_str(ap._str)
	{
		ap._str = NULL;
	}
	AutoPtr<T>& operator=(AutoPtr<T>& ap)
	{
		if(this != &ap)
		{
			delete _str;
			_str = ap._str;
			ap._str = NULL;
		}
		return *this;
	}
	~AutoPtr()
	{
		if(_str)
			delete _str;
	}
public:
	T& operator*()
	{
		return *_str;
	}
	T* operator ->()
	{
		return _str;
	}
private:
	T* _str;
};
 
struct A
{
	int _a;
};

void Test4()
{
    AutoPtr<int>ap(new int(1));
    AutoPtr<int>ap2(ap);
    AutoPtr<int>ap3(new int(2));
    AutoPtr<int>ap4(ap3);
    ap4 = ap;
}

int main()
{
    Test4();
    return 0;
}

显示结果:

技术分享

当然这个结果是正确的,但是你要这个AutoPtr又有什么用,你用对象之间拷贝构造新对象和对象之间相互赋值时,就是为了让他们共同管理,但是现在,这就有点low了,既没有达到那种共同管理,也在拷贝构造对象和相互赋值时,不清不楚,所以他很low.当然有些技术大牛早就看这个不顺眼了,于是自己弄出来既可以解决自动管理内存的释放,也可以用对象之间拷贝构造新对象和对象之间相互赋值,达到你想要的那种效果,没毛病,待续...

                                                    技术分享

本文出自 “Pzd流川枫” 博客,请务必保留此出处http://xujiafan.blog.51cto.com/10778767/1761067

C++_智能指针

标签:智能指针 raii

原文地址:http://xujiafan.blog.51cto.com/10778767/1761067

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!