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
原创粉丝点击