析构函数是怎样的
-
~类名();
class MM
{
public:
~MM() //析构函数
{
}
};
-
没有返回值
void print(); //这个函数有返回值,返回值是void,无返回值: 没有(void)这个类型
-
什么时候需要自己手动写析构函数(一般可以不写)
-
析构函数是用来释放数据成员申请的内存,当类中的数据成员是指针,并且构造函数中做了动态内存申请就需要手写析构
析构函数的特点
-
析构函数不需要手动调用,对象消亡之前会调用析构函数--->调用析构函数不能直接消亡对象,只是对象消亡前的通知(调用析构函数不是结束生命周期)
-
无参数--->析构函数不能被重载
- 不写析构函数,会存在一个默认的析构函数
小知识:
-
做了动态内存申请,程序关闭,内存被回收,为什么还要释放? 程序运行,进程一直都在,程序占用的内存越来越大,从而造成内存泄漏
-
可以自己写一个函数手动释放内存吗? 可以但没必要,可能存在释放了内存下面接着使用这段内存的可能--->推荐使用析构函数,什么时候不用这段内存了再自动释放内存
-
为什么要手动写析构函数? 因为默认的不会释放数据成员动态申请的内存
-
本文未涉及:构造函数中做了new内存操作时,通过一个对象去创建另一个新的对象,释放内存时重复调用析构函数,导致程序中断的问题,详情请转:c++深、浅拷贝 - - - 调用构造函数构造对象时中做了new内存操作需要注意的问题_考拉爱睡觉鸭~的博客-CSDN博客
class MM
{
public:
MM(const char* pstr,int age):age(age)
{
pstr = new char[strlen(pstr) + 1];
strcpy_s(str,strlen(pstr) + 1,pstr);
}
void print()
{
cout << str << "\t" << age << endl;
}
void freeMemory()
{
delete[] str;
}
~MM();
protected:
char* str;
int age;
};
MM::~MM()
{
cout << "调用析构函数" << endl;
delete[] str;
}
int main()
{
MM mm("张三", 18);
mm.print();
mm.freeMemory();
mm.print();
cout << "主函数" << endl;
return 0;
}
/*输出*/
张三 18
葺葺葺葺葺葺葺葺疲峱? 18
主函数
调用析构函数
析构函数的使用
#include <cstring> //C语言的string
class MM
{
public:
MM(const char* pstr,int age):age(age)
{
pstr = new char[strlen(pstr) + 1]; //数据成员做了动态内存申请
strcpy_s(str,strlen(pstr) + 1,pstr);
}
void print()
{
cout << str << "\t" << age << endl;
}
~MM(); //类中声明
protected:
char* str;
int age;
};
MM::~MM() //类外实现,用类名限定即可(构造函数也一样)
{
cout << "调用析构函数" << endl;
delete[] str;
}
int main()
{
{
MM mm("张三", 18);
mm.print();
} //对象出了{}就消亡了,生命周期结束,在下一句代码执行前调用析构函数
cout << "主函数" << endl;
return 0;
}
/*输出*/
张三 18
调用析构函数
主函数
小知识:
用析构函数有必要 | 可以自己手动调用释放内存吗?
如果手动调用--->对象消亡还是会调用,出现2次释放问题--->导致程序中断、内存被重复释放了
int main()
{
{
MM mm("张三", 18);
mm.~MM(); //手动调用析构函数
}
cout << "主函数" << endl;
return 0;
}
/*输出 程序中断*/
调用析构函数
调用析构函数
...
把{ }去掉,程序执行到return 0;还是会自动调用析构函数
int main()
{
MM mm("张三", 18);
mm.~MM(); /*调用析构函数*/
cout << "主函数" << endl;
return 0; /*调用析构函数*/
}
/*输出 程序中断*/
调用析构函数
主函数
调用析构函数
...
new一个对象的时候,只有delete 才会调用析构函数
//未delete没有调用析构函数--->对象未消亡
int main()
{
{
MM* pObject = new MM("小李", 12); //在堆区,对象没有死亡
}
return 0;
}
/*输出*/
没有调用析构函数
int main()
{
{
MM* pObject = new MM("小李", 12);
delete pObject; //delete[] pObject单个只能对应单个 多个可以对应单个|多个
pObject = nullptr;
}
return 0;
}
/*输出*/
调用析构函数