什么析构函数?
析构函数和构造函数一样,析构函数也是类的特殊成员函数,不用调用便自动执行,而且析构函数的名字也是与类的名字有关。
·
在前面我们可以知道,c++程序设计的一个原则是,由系统自动分批的内存空间由系统自动释放,而手工分配的内存空间必须手动释放,否则可能会造成内存的泄露。
·
我们先看如下问题实例:
#include<iostream>
#include<cstring>
using namespace std;
class my
{
int n;
char* p;
public:
my(int na, char* pa)
{
n = na;
p = new char[20];
strcpy(p, pa);
}
void print()
{
cout << "n:" << n << " " << "p:" << p << endl;
}
};
int main()
{
my a(1, "mary");
a.print();
return 0;
}
上面程序是可以正常运行的,但是的确的存在问题。
当我们定义my的类对象a时,此对象如图所示
在构造函数中为pname的指针分配指向的内存空间,然后赋值“mary”字符串,但是程序执行完,pname所指向的空间没有释放。
解决问题的方法是使用析构函数,就是将pname所指向的空间的代码放在析构函数中,my类所示的析构函数如下图所示:
~my
{
delete pname;
}
从这个例子中我们可以看出,一个类可以在构造函数中里分配资源,这些资源需要在对象不复存在以前被释放。析构函数就是完成这种释放资源的清理工作的。
如同默认构造函数一样,如果一个类没有定义析构函数,编译器会自动生成一个默认的析构函数。
·
·
析构函数的性质
·析构函数在类的对象销毁时自动执行
·一个类只能有一个析构函数,而且析构函数没有参数
·析构函数的名字时“~”加上类的名字(中间没有空格)
·与构造函数一样,析构函数没有任何类型,既不属于返回值函数也不属于void函数,他们不能像其他函数那样被调用
·
·
析构函数的调用
1·用类直接建立对象
#include<iostream>
using namespace std;
class reca
{
private:
int x1, x2, y1, y2;
public:
reca(int a1, int b1, int a2, int b2)
{
cout << "调用到参数构造函数" << endl;
x1 = a1;
x2 = a2;
y1 = b1;
y2 = b2;
}
reca()
{
cout << "调用无参构造函数" << endl;
x1 = 0;
y1 = 0;
x2 = 0;
y2 = 0;
}
int area()
{
return (x2 - x1) * (y2 - y1);
}
~reca()
{
cout << "调用了析构函数" << endl;
}
};
int main()
{
reca r1(1, 3, 8, 12);
cout << "矩形r1的面积:" << r1.area()<< endl;
reca r2;
cout << "矩形r2的面积:" << r2.area()<< endl;
return 0;
}
在上述程序中,对象r1,r2在主程序中main()结束遇到后括号时,会自动那调用析构函数,因此输出的结果中会有两个“调用了析构函数”.
`
`
`
2用new动态创建对象
对于用new运算动态创建的对象,在产生对象时调用构造函数,只有用delete释放对象时,才会调用析构函数。若不使用delete运算符来撤销动态生成的对象,程序结束时对象仍存在,并占用相应的存储空间,即系统不能自动撤销动态创建的对象。
认真分析如下实例:
#include<iostream>
using namespace std;
class tpoint
{
int x, y;
public:
tpoint(int x1, int y1)
{
x = x1;
y = y1;
}
~tpoint()
{
cout << "调用析构函数" << endl;
}
void dispoint()
{
cout << "(" << x << "," << y << ")" << endl;
}
};
int main()
{
tpoint a(12, 6);
tpoint* p;
p = new tpoint(4, 13);
cout << "First point =>";
a.dispoint();
cout << "Second point =>";
p->dispoint();
delete p;
return 0;
}
从程序的执行结果可以看出,对于类对象,系统会自动释放它并且自动调用析构函数,程序中的对象
a就是这样的。
对于用new运算符创建的对象,必须在delete运算符释放时才能调用析构函数,程序中的对象指针p使用delete释放,所以调用析构函数。
·
·
·如果我们不使用 new,delete,析构函数的话,应该这样做:
int main()
{
tpoint a(12, 6);
tpoint* p;
tpoint q(4,13);
p = &q;
cout << "First point =>";
a.dispoint();
cout << "Second point =>";
p->dispoint();
return 0;
}
因为这个tpoint只是一个类的名字,不是变量,不可以分配内存,没有地址。所以我们还应该在声明一个变量,如上图所示。
·
·
·
认真分析经典例题:
#include<iostream>
using namespace std;
class line
{
public:
void setlength(double len);
double getlength(void);
line();
~line();
private:
double length;
};
line::line(void)
{
cout << "object is being created" << endl;
}
line::~line(void)
{
cout << "deleted" << endl;
}
void line::setlength(double len)
{
length = len;
}
double line::getlength(void)
{
return length;
}
int main()
{
line lin;
lin.setlength(6.0);
cout << "lenght of line is" << lin.getlength()<< endl;
return 0;
}
我们在做题的过程中一般不会主动使用new和delete,只有在题目中要求了,我们才会使用。
——本文转载至资料,仅用于个人学习
——2021年4月19日19:46