C/C++——跟我重写智能指针auto_ptr模版类
2016-05-10 21:47
375 查看
第一次使用auto_ptr的时候感觉很好用,但是对内部原理根本不懂,心里不知道这东西到底是个什么东东,总是感觉这东东比较陌生。今天有时间来简单实现一下该类模版auto_ptr,实现了该模版类的主要功能,可以让大家了解一下这个东东内部到底是个什么情况。
如果看到这里,你不清楚堆和栈的区别。那我也不解释了,自行Google..(如果你想baidu也不拦你)
1、先测试栈上分配的对象
程序输出为:
从输出结果可以看出,在栈上分配的对象在离开作用域的时候会自动调用析构函数,不用手动释放。
2、再测试堆上分配的对象
将上面的main函数改为下面:
程序输出为:
从输出结果可以看出,在堆上分配的对象在离开作用域的时候不会自动调用析构函数,需要手动释放。
下面是添加手动释放对象的语句:
下面是改了之后的程序输出:
那么就想啊,有什么办法可以像栈对象那样操作堆对象。栈对象是在栈内存空间的对象,当对象超过作用域的时候会自动释放。那么我们可以让栈内存空间上的一个指针对象专门来管理堆对象,当指针对象离开作用域的时候肯定会调用自身的析构函数,那么我们在指针对象的析构函数中对它管理的堆对象内存空间进行释放。
程序输出为:
在上面的例子中可以看出,auto_ptr是一个模版类,我们在这里定义了一个管理类A对象的一个指针对象ptr,该指针对象ptr可以使用运算符->和*,所以在类auto_ptr中重载了运算符->和*。
在上面例子中的指针对象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()
为什么需要智能指针?
从上面的例子可以看出,对于在堆上分配的对象的释放是一件比较麻烦的事情,如果忘了手动释放,那就会造成内存的泄漏。如果全部收到释放,那么又给程序员带来很大的麻烦。那么就想啊,有什么办法可以像栈对象那样操作堆对象。栈对象是在栈内存空间的对象,当对象超过作用域的时候会自动释放。那么我们可以让栈内存空间上的一个指针对象专门来管理堆对象,当指针对象离开作用域的时候肯定会调用自身的析构函数,那么我们在指针对象的析构函数中对它管理的堆对象内存空间进行释放。
智能指针auto_ptr简单应用实例:
#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()
在上面的例子中可以看出,auto_ptr是一个模版类,我们在这里定义了一个管理类A对象的一个指针对象ptr,该指针对象ptr可以使用运算符->和*,所以在类auto_ptr中重载了运算符->和*。
在上面例子中的指针对象ptr是栈对象,在离开作用域的时候会自动释放,然后会自动调用析构函数,在它的析构函数中会释放它指向的堆对象,从而达到了智能指针的效果。
重写智能指针模版类SmartPointer:
/**************************************** * 类名称: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; };
在程序中可以看出,该模版类重载了运算符->和*,并实现了管理堆对象的功能。
下面是测试智能指针模版类SmartPointer:
/*************************************************************************
> 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()
从输出结果可以看出该模版类智能指针也实现了管理堆对象的功能。
相关文章推荐
- C++函数
- c++第五次上机实验--项目一、项目五
- C++四种强制类型转换关键字
- C++作业5
- C++第五次上机实验--数组分离
- c++实验5,求和
- C/C++程序运行时进程的内存分布情况
- 学生宿舍管理系统 150809205
- C语言课程设计第三节课:指针和链表使用 150809205
- Effective C++----3rd Edition, Item 2:用consts,enums和inlines取代#define
- C语言 O(1)的时间删除链表节点
- C++实现数组中出现最频繁的前top k个元素
- C语言 整数的整数次方(不考虑大数问题)
- C++ Primer 学习笔记_94_用来大型程序的工具 -命名空间[续3]
- C语言 二进制中1的个数
- C语言 打印1到最大的N位数(输入3,打印1,2,3~999)
- c++作业5
- 第7周 C语言及程序设计提高例程-27 编写查找和排序函数(有疑问)
- C语言 调整一个数组的顺序,使得奇数在总在偶数的前边
- C语言 斐波那契数列