C++智能指针(一)——auto_ptr

 智能指针的发展历程

 

其中shared_ptr和scoped_ptr的应用范围更大一些。在单例中,shared_ptr比较好用。 

 

 

智能指针

 

用来托管自定义类型对象,让在上创建的自定义对象可以自动释放

通过写一个智能指针类,通过智能指针类来创建自定义类的对象。在栈上创建智能指针对象,这样,智能指针对象被释放的时候,就把利用智能指针在堆上创建的自定义对象给一并析构了。

为了让智能指针指向自定义类类型指针的功能一样,需要重载->和*.

 

智能指针的例子如下:

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person{
public:
	Person(int age){
		this->m_Age = age;
	}
	void showAge(){
		cout << "年龄为:" << this->m_Age << endl;
	}
	~Person(){
		cout << "Person的析构调用" << endl;
	}
	int m_Age;
};


//智能指针
//用来托管自定义类型的对象,让对象进行自动的释放
class smartPointer{
public:
	smartPointer(Person * person){
		this->person = person;
	}
	//重载->让智能指针对象 想Person *p一样去使用
	Person * operator->(){
		return this->person;
	}
	//重载 * 
	Person& operator*(){		
		return *this->person;
	}
	~smartPointer(){
		cout << "智能指针析构了" << endl;
		if (this->person !=NULL){
			delete this->person;
			this->person = NULL;
		}
	}

private:
	Person * person;
};

void test01(){
	//sp开辟到了栈上,自动释放,sp就是智能指针了
	smartPointer sp(new Person(10)); 
	// sp->->showAge(); 编译器优化了 写法
	sp->showAge(); 
	(*sp).showAge();
}


int main(){

	test01();
	system("pause");
	return EXIT_SUCCESS;
}

 

 

auto_ptr

auto_ptr是C++标准库中(<memory>)为了解决资源泄漏的问题提供的一个智能指针类模板(注意:这只是一种简单的智能指针) 
auto_ptr的实现原理其实就是RAII(Resource Application Immediately Initialize),即资源的分配及初始化,定义一个类来封装资源的分配及释放,在构造函数中完成资源的分配和初始化,在析构函数中完成资源的清理。

智能指针的目的是实现资源的管理,有三种方法来进行资源的管理

  • 资源转移— auto_ptr
  • 防拷贝    —scoped_ptr
  • 引用计数—shared_ptr

 

作用

使用auto_ptr作为成员变量,以避免资源泄漏。

为了防止资源泄漏,我们通常在构造函数中申请,析构函数中释放,但是只有构造函数调用成功,析构函数才会被调用,换句话说,如果在构造函数中产生了异常,那么析构函数将不会调用,这样就会造成资源泄漏的隐患

比如,如果该类有2个成员变量,指向两个资源,在构造函数中申请资源A成功,但申请资源B失败,则构造函数失败,那么析构函数不会被调用,那么资源A则泄漏。

为了解决这个问题,我们可以利用auto_ptr取代普通指针作为成员变量,这样首先调用成功的成员变量的构造函数肯定会调用其析构函数,那么就可以避免资源泄漏问题

 

 

注意

  • auto_ptr存储的指针应该为NULL或者指向动态分配的内存块。
  • auto_ptr存储的指针应该指向单一物件(是new出来的,而不是new[]出来的)。
  • 两个auto_ptr对象不会同时指向同一块内存块。要明白2个auto_ptr对象赋值会发生什么。
  • 千万不要把auto_ptr对象放在容器中
  • 当将auto_ptr作为函数参数时,最好声明为const auto_ptr&(by const ref).当函数返回值可以简单的传值(by value).

 

 

auto_ptr类

auto_ptr是一个模板类,定义如下:

template <typename Type>
class auto_ptr {...};

它存储的是一个指向Type的指针。

顾名思义,auto_ptr是一种智能指针,它包含一个动态分配内存的指针,并在它生命周期结束的时候,销毁包含的指针所指向的内存。

引发内存泄漏的例子:

void f() {
    Type* pt(new Type);
    //一些代码...
    delete pt;
}

这样的代码很常见,但它有可能造成内存泄露。首先你用了new,你就要记得用delete,但即使你记住了用delete,还是会出问题。如果f()在执行delete pt之前,就抛出了异常,函数返回了。那么这个分配的对象就没被删除。

使用auto_ptr,很优雅的解决了这些问题:

void f(){
    auto_ptr<Type> pt(new Type);
    //一些代码...
}

现在的代码,不会泄露Type类型的对象。不管是函数正常结束,还是抛出异常结束,都会调用pt的析构函数,从而删除分配的对象。

 

 

简版auto_ptr类(代码来源——《STL源码剖析》P81)

template<class T>
class autp_ptr {
public:
        //构造函数
	explicit auto_ptr(T* p=0):pointee(p){}

        //拷贝构造函数
	template<class U>
	auto_ptr(autp_ptr<U>& rhs):pointee(rhs.release()){}
	~auto_ptr() { delete pointee; }

        //拷贝赋值函数
	template<class U>
	auto_ptr<T>& operator=(auto_ptr<U>& rhs) {
		if (this != &rhs) reset(rhs.release());
		return *this;
	}

	T& operator*() const { return *pointee; }
	T* operator->() const { return pointee; }
	T* get() const { retuen pointee; }
	//...
private:
	T *pointee;
};

代码分析:

构造函数:

explicit auto_ptr(T* p=0):pointee(p){}

auto_ptr<int> pt;                 //包含一个int*的指针,并初始化为NULL
auto_ptr<int> pt(new int(123));   //包含一个int*的指针,并初始化为123的地址
auto_ptr<int> pt = new int(123);  //error! 构造函数声明为explicit

拷贝构造函数:

template<class U>
auto_ptr(autp_ptr<U>& rhs):pointee(rhs.release()){}

int* ptr = new int();
auto_ptr<int> pt1(ptr); //构造函数1
auto_ptr<int> pt2(pt1); //将pt1的使用权转给pt2,注意pt1指向NULL了
                        //pt1调用了本身的release()函数,将内部指针地址传给pt2

拷贝复制函数:

template<class U>
auto_ptr<T>& operator=(auto_ptr<U>& rhs) ;

class Base {};
class Derived : public Base {};

auto_ptr<Derived> pDerived(new Derived);
auto_ptr<Base>=pBase(pDerived);           //让这样的代码能通过编译器其本质是为了让,
                                          //auto_ptr类内部的Derived*转换为Base*

 

 

 

 

参考文献

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值