C++学习笔记37——析构函数
来源:互联网 发布:java软件工程师查工资 编辑:程序博客网 时间:2024/06/05 17:46
1,什么是析构函数
析构函数是,当对象超出作用域或显式删除对象时,用于清除对象的特殊成员函数。
析构函数的名字是在类名前加一个取反运算符“~”。
析构函数的作用并不是删除对象,而是在撤销对象占用的内存之前完成一些清理工作。
一个类可以有多个构造函数,但只有一个析构函数,言外之意,析构函数不能重载。
2,系统在什么时候调用析构函数
总的来说两种情况:
(1)对象超出作用域;
(2)显式删除对象(delete)
详细来说分如下4种情况:
(1)自动局部变量,当定义该局部变量的函数调用结束时,对象应该释放,在对象释放前自动执行析构函数;
(2)静态局部对象,在函数调用结束时并不释放,因此也不调用析构函数,只在main()函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数;
(3)全局对象,在程序的流程离开其作用域时(如main()函数结束或调用exit函数结束程序时),调用该全局对象的析构函数;
(4)用new运算符动态创建的对象,当用delete运算符释放该对象时,先调用该对象的析构函数。
3,合成析构函数
与复制构造函数和赋值运算符不同,不管你定不定义自己的析构函数,编译器总是会合成一个析构函数,称为“合成析构函数”。
合称析构函数按照对象创建时的逆序撤销每个非static成员,因此,它按成员在类中声明次序的逆序撤销成员。对于类类型的成员,合成析构函数调用该成员的析构函数来撤销对象。合成析构函数并不删除指针成员指向的对象,所以如果指针指向的对象是在构造函数中动态分配的,则我们应该在自己定义的析构函数中收回这一部分内存。
即便我们编写了自己的析构函数,合成析构函数仍然运行。
4,示例
/*******************************************************************/// 析构函数/*******************************************************************///定义类class Dynamic_Array{public:Dynamic_Array():array_size(0), p_arr(NULL) {} //默认构造函数Dynamic_Array(int len); //构造函数explicit Dynamic_Array(const vector<double> &d_vec);Dynamic_Array(const Dynamic_Array &dyn_arr); //复制构造函数Dynamic_Array& operator=(const Dynamic_Array &dyn_arr); //赋值操作符~Dynamic_Array(); //析构函数void show_array(); //一般成员函数void set_array(const vector<double> &d_vec);private:size_t array_size;double *p_arr;};//定义成员函数Dynamic_Array::Dynamic_Array(int len){array_size = len;p_arr = new double[array_size];memset(p_arr,0, array_size*sizeof(double));cout << "调用构造函数, array_size = " << array_size << endl;}Dynamic_Array::Dynamic_Array(const vector<double> &d_vec){array_size = d_vec.size();p_arr = new double[array_size];for (size_t index = 0; index != array_size; index++){p_arr[index] = d_vec[index];}cout << "调用构造函数, array_size = " << array_size << endl;}Dynamic_Array::Dynamic_Array(const Dynamic_Array &dyn_arr){array_size = dyn_arr.array_size;p_arr = new double[array_size];memset(p_arr, 0, array_size*sizeof(double));cout << "调用复制构造函数, array_size = " << array_size << endl;}Dynamic_Array& Dynamic_Array::operator=(const Dynamic_Array &dyn_arr){array_size = dyn_arr.array_size;p_arr = new double[array_size];for (size_t index = 0; index != array_size; index++){p_arr[index] = dyn_arr.p_arr[index];}cout << "调用赋值操作符, array_size = " << array_size << endl;return *this;}Dynamic_Array::~Dynamic_Array(){delete []p_arr;array_size = 0;cout << "调用析构函数" << endl;}void Dynamic_Array::show_array(){for (size_t index = 0; index != array_size; index++){cout << p_arr[index] << endl;}}void Dynamic_Array::set_array(const vector<double> &d_vec){if (array_size < d_vec.size()){delete[] p_arr;p_arr = new double[array_size];array_size = d_vec.size();}for (size_t index = 0; index != d_vec.size(); index++){p_arr[index] = d_vec[index];}}// 定义普通函数void show_destructor(){vector<double> d_vec(5, 520);Dynamic_Array arr(d_vec);arr.show_array();}//主函数int main(){show_destructor();cout << "after call the show_destructor()" << endl;system("pause");return 0;}
输出结果:
show_destructor()函数调用结束后,在函数内定义的局部变量要收回,所以调用了析构函数。
5,多态类中的析构函数
多态类:定义了虚函数的类称为多态类,多态类通常用于继承。如果有一个多态基类类型的指针或引用,而其实际上指向的是派生类的对象,则用这个引用或指针调用virtual函数时就会发生所谓的“动态绑定”。
多态时最好将基类的析构函数设为virtual,这样在析构时会先调用子类的析构函数,再调用基类的析构函数,否则如果delete的是基类的指针(而实际指向派生类),则只调用基类的析构函数,不调用派生类的析构函数,可能造成内存泄漏。
而派生类的析构函数是否定义成virtual无所谓(除非派生类还会继续被继承),因为调用派生类的析构函数时,总是会调用到基类的析构函数。
0 0
- 【C++】学习笔记四十七——类的构造函数和析构函数
- C++:函数<学习笔记>
- C++学习笔记37——析构函数
- 学习C++——构造函数和析构函数
- C与指针学习笔记——函数指针
- c语言学习笔记(8)——函数
- 多态性与虚函数——C/C++学习笔记
- 【C++】学习笔记二十九——函数
- 【C++】学习笔记三十一——函数和数组
- 【C++】学习笔记三十二——函数和二维数组
- 【C++】学习笔记三十四——函数和结构
- 【C++】学习笔记三十五——函数和string对象
- 【C++】学习笔记三十六——函数和array对象
- 【C++】学习笔记三十八——函数指针
- C++PrimerPlus第八章学习笔记——函数探幽
- 【C++】学习笔记三十九——内联函数
- 【C++】学习笔记四十二——函数重载
- 【C++】学习笔记四十三——函数模板
- Android中shareSDK使用时注意事项
- Mex的结构
- C# 实现可克隆(ICloneable)的类型
- [转]移动前端开发之viewport的深入理解
- 四、将数据库表导入到solr索引
- C++学习笔记37——析构函数
- SDUT 数据结构实验之查找四:二分查找
- 最全的常用正则表达式大全——包括校验数字、字符、一些特殊的需求等等
- 堆栈练习
- 解决ScrollView嵌套ListView显示不完全和滑动冲突的问题
- JAVA 简单使用JDBC实现连接数据
- swift-基础04-数字类型转换
- JavaWeb Session问题整理
- 队列练习