第一次使用auto_ptr的时候感觉很好用,但是对内部原理根本不懂,心里不知道这东西到底是个什么东东,总是感觉这东东比较陌生。今天有时间来简单实现一下该类模版auto_ptr,实现了该模版类的主要功能,可以让大家了解一下这个东东内部到底是个什么情况。
首先,看一下两种类对象的区别,一个是在栈上分配空间,另一个是在堆上分配空间。
如果看到这里,你不清楚堆和栈的区别。那我也不解释了,自行Google..(如果你想baidu也不拦你)
1、先测试栈上分配的对象
#include <iostream> #include <memory> using namespace std; /**************************************** * 类名称:A(用于测试的类) ****************************************/ class A { public: A(int num):a(num){cout << "A(int num)" << endl;} A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} void func(){ cout << "A.fun()" << endl; } private: int a; }; /**************************************** * 主测试函数main ****************************************/ int main() { A a1; a1.func(); //A * pa = new A(); //pa->func(); return 0; }
A() A.fun() ~A()
2、再测试堆上分配的对象
将上面的main函数改为下面:
/**************************************** * 主测试函数main ****************************************/ int main() { //A a1; //a1.func(); A * pa = new A(); pa->func(); return 0; }
A() A.fun()
下面是添加手动释放对象的语句:
/**************************************** * 主测试函数main ****************************************/ int main() { //A a1; //a1.func(); A * pa = new A(); pa->func(); delete pa; return 0; }
A() A.fun() ~A()
从上面的例子可以看出,对于在堆上分配的对象的释放是一件比较麻烦的事情,如果忘了手动释放,那就会造成内存的泄漏。如果全部收到释放,那么又给程序员带来很大的麻烦。
那么就想啊,有什么办法可以像栈对象那样操作堆对象。栈对象是在栈内存空间的对象,当对象超过作用域的时候会自动释放。那么我们可以让栈内存空间上的一个指针对象专门来管理堆对象,当指针对象离开作用域的时候肯定会调用自身的析构函数,那么我们在指针对象的析构函数中对它管理的堆对象内存空间进行释放。
#include <iostream> #include <memory> using namespace std; /**************************************** * 类名称:A(用于测试的类) ****************************************/ class A { public: A(int num):a(num){cout << "A(int num)" << endl;} A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} void func(){ cout << "A.fun()" << endl; } private: int a; }; /**************************************** * 主测试函数main ****************************************/ int main() { //使用智能指针模版类auto_ptr //new A等价于new A(),但是如果有括号的话,可以调用带参的构造函数,如new A(10); auto_ptr<A> ptr(new A); ptr->func(); (*ptr).func(); return 0; }
A() A.fun() A.fun() ~A()
在上面例子中的指针对象ptr是栈对象,在离开作用域的时候会自动释放,然后会自动调用析构函数,在它的析构函数中会释放它指向的堆对象,从而达到了智能指针的效果。
/**************************************** * 类名称:Smart智能指针模版类 ****************************************/ template<typename T> class SmartPointer { public: //构造函数 SmartPointer(T * p = NULL):ptr(p){ } //析构函数 ~SmartPointer(){ if(ptr != NULL) delete ptr; } //重载->运算符 T * operator->(){ return ptr; } //重载*运算符 T & operator*(){ return *ptr; } private: T * ptr; };
/************************************************************************* > File Name: smartPointerTemplate.cpp > Author: > Mail: > Created Time: 2016年05月10日 星期二 19时26分14秒 ************************************************************************/ #include <iostream> using namespace std; /**************************************** * 类名称:A(用于测试的类) ****************************************/ class A { public: A(int num):a(num){cout << "A(int num)" << endl;} A(){cout << "A()" << endl;} ~A(){cout << "~A()" << endl;} void func(){ cout << "A::fun()" << endl; } private: int a; }; /**************************************** * 类名称:B(用于测试的类) ****************************************/ class B { public: B(){cout << "B()" << endl;} ~B(){cout << "~B()" << endl;} void func(){ cout << "B::func()" << endl; } }; /**************************************** * 类名称:Smart智能指针模版类 ****************************************/ template<typename T> class SmartPointer { public: //构造函数 SmartPointer(T * p = NULL):ptr(p){ } //析构函数 ~SmartPointer(){ if(ptr != NULL) delete ptr; } //重载->运算符 T * operator->(){ return ptr; } //重载*运算符 T & operator*(){ return *ptr; } private: T * ptr; }; /**************************************** * 主测试函数main ****************************************/ int main() { SmartPointer<A> smt(new A()); smt->func(); (*smt).func(); SmartPointer<B> smtB(new B()); smtB->func(); (*smtB).func(); return 0; }
A() A::fun() A::fun() B() B::func() B::func() ~B() ~A()