ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

如果没有显式声明析构函数,编译器默认生成的析构函数长什么样?它的行为是什么?

2026/9/6 7:54:47 拓冰建站 浏览量
如果没有显式声明析构函数,编译器默认生成的析构函数长什么样?它的行为是什么? 一句话回答编译器生成的默认析构函数长这样~Cat(){// 啥也不写空函数体}但别被表面骗了——它虽然看起来是空的但背后会自动调用所有成员变量和基类的析构函数。默认析构函数具体干了什么编译器生成的默认析构函数等价于~Cat(){// 1. 自动调用所有成员对象的析构函数如果有的话// 2. 自动调用所有基类的析构函数如果有继承的话// 3. 对于基本类型int、char*、const char等啥也不做直接回收栈内存}成员类型默认析构函数怎么处理举例基本类型int、char、double等啥也不干直接回收栈空间happiness、hungry、health直接消失指针类型char*、int*等啥也不干只回收指针变量本身4/8字节不释放指针指向的堆内存name指针变量被回收但多多那块堆内存泄漏了类类型成员std::string、vector等自动调用它们自己的析构函数如果成员是std::string它会自动delete[]自己的内部数组用你的Cat类举例如果你不写析构函数默认的classCat{private:inthappiness;// 基本类型 → 啥也不干直接回收inthungry;// 基本类型 → 啥也不干直接回收inthealth;// 基本类型 → 啥也不干直接回收constcharsex;// 基本类型 → 啥也不干直接回收char*name;// 指针类型 → 只回收指针变量本身不释放堆内存};结果name指向的多多那块堆内存永远没人释放 →内存泄漏。所以你的Cat类必须自己写析构函数~Cat(){delete[]name;// 必须手动释放}如果你把name换成std::string推荐做法#includestringclassCat{private:std::string name;// 类类型自带析构函数// ... 其他成员};这时候可以不写析构函数因为std::string的析构函数会自动释放内部堆内存基本类型int、char直接回收没有额外资源需要清理默认析构函数会调用name.~string()而~string()负责释放字符串内存。默认析构函数的隐藏动作示意图~Cat()// 编译器生成的默认版本{// ① 按声明顺序的逆序自动调用成员对象的析构函数// 如果成员是 std::string调用 ~string()// 如果成员是另一个 class 对象调用它的析构函数// ② 自动调用基类的析构函数如果有继承// ③ 函数体结束栈内存int、指针本身被回收}什么时候可以偷懒不写析构函数情况需要自己写析构函数吗所有成员都是基本类型int、char、double❌ 不需要所有成员都是类类型std::string、vector、其他类对象❌ 不需要有原始指针char*、int*且new过✅必须写要delete[]有文件句柄、数据库连接等资源✅必须写要关闭释放有std::shared_ptr智能指针❌ 不需要它会自动释放一句话总结默认析构函数是空的但会自动清理成员对象它不会释放你手动new出来的堆内存所以只要你的类里有new过的原始指针就必须自己写析构函数去delete它。