
前言在 C 面向对象编程中类是模板对象是实例。我们创建对象时往往需要自动初始化成员变量对象销毁时需要释放堆内存、关闭文件、释放资源这两个核心工作就交给了构造函数与析构函数。很多初学者分不清构造、析构的调用时机、语法规则、重载特性经常出现内存泄漏、野指针、对象初始化混乱等问题。本文从零梳理构造函数、析构函数全部核心知识点附带完整可运行代码适合期末复习、面试速记。一、构造函数详解1. 定义与核心作用构造函数是与类同名、无返回值的特殊成员函数创建对象时自动调用。 核心作用安全初始化对象的成员变量保证对象诞生时处于合法可用状态。2. 构造函数硬性语法规则函数名必须和类名完全一致没有返回值不能写void、int等可以有参数支持函数重载不能手动调用创建对象时编译器自动执行一个类可以拥有多个重载构造函数。3. 分类与代码示例1无参构造默认构造不传入任何参数成员变量赋默认值。cpp运行#include iostream using namespace std; class Person { public: int age; // 无参构造函数 Person() { age 0; cout 无参构造函数执行 endl; } }; int main() { Person p; // 创建对象自动调用无参构造 cout p.age endl; return 0; }2有参构造传入参数自定义初始化成员支持多种参数格式重载。cpp运行class Person { public: int age; string name; // 单参数构造 Person(int a) { age a; cout 有参构造(年龄)执行 endl; } // 双参数构造重载 Person(int a, string n) { age a; name n; cout 有参构造(年龄姓名)执行 endl; } }; int main() { Person p1(18); Person p2(20, 张三); return 0; }3拷贝构造函数格式类名(const 类名 对象)使用已有对象复制出新对象。 触发场景使用一个对象初始化另一个对象函数形参为类对象值传递函数返回类对象值返回。cpp运行class Person { public: int age; Person(int a) { age a; } // 拷贝构造函数 Person(const Person p) { age p.age; cout 拷贝构造执行 endl; } }; int main() { Person p1(18); Person p2 p1; // 触发拷贝构造 return 0; }4. 初始化列表推荐初始化方式构造函数内赋值是 “先创建再赋值”初始化列表直接创建时赋值效率更高const 成员、引用成员必须用初始化列表。cpp运行class Person { public: const int id; int age; // 初始化列表 Person(int i, int a) : id(i), age(a) { } };二、析构函数详解1. 定义与核心作用析构函数是对象销毁时自动调用的特殊函数负责资源清理释放 new 开辟的堆内存、关闭文件、释放锁等防止内存泄漏。2. 析构函数硬性语法规则函数名~类名前面加波浪号无参数、无返回值一个类只能有一个析构函数不支持重载对象销毁时自动调用栈对象出作用域、堆对象delete时触发。3. 基础示例堆内存释放场景cpp运行#include iostream #include cstring using namespace std; class Person { public: char* name; // 构造函数开辟堆内存 Person(const char* n) { name new char[strlen(n) 1]; strcpy(name, n); } // 析构函数释放堆内存 ~Person() { delete[] name; cout 析构函数执行释放内存 endl; } }; int main() { Person p(李四); // 函数结束p销毁自动调用析构 return 0; }4. 析构函数调用时机区分栈对象离开当前大括号作用域自动调用堆对象必须手动delete才会执行析构不 delete 会内存泄漏。cpp运行int main() { // 栈对象 { Person p1(小王); } // 出作用域p1析构 // 堆对象 Person* p2 new Person(小李); delete p2; // 手动释放触发析构 return 0; }三、构造与析构配套高频考点1. 默认生成规则类不写任何构造编译器自动生成默认无参构造类写了有参构造编译器不再提供默认无参构造不手动写析构编译器生成默认析构仅简单销毁栈成员不会释放堆内存。2. 构造、析构调用顺序局部对象先构造后析构多个栈对象先创建的对象后析构后创建的先析构。cpp运行int main() { Person p1(A); Person p2(B); // 析构顺序p2 → p1 return 0; }3. 深浅拷贝与析构避坑如果类内有堆指针编译器默认拷贝构造是浅拷贝多个对象指向同一块堆内存析构时重复释放同一块内存程序崩溃。 解决方案手动写深拷贝构造为新对象重新开辟堆内存。四、完整综合案例构造 析构 初始化列表cpp运行#include iostream #include cstring using namespace std; class Student { public: int id; char* name; // 无参构造 Student() : id(0) { name new char[4]; strcpy(name, 未知); cout 无参构造执行 endl; } // 有参构造 Student(int i, const char* n) : id(i) { name new char[strlen(n) 1]; strcpy(name, n); cout 有参构造执行 endl; } // 拷贝构造深拷贝 Student(const Student s) : id(s.id) { name new char[strlen(s.name) 1]; strcpy(name, s.name); cout 拷贝构造执行 endl; } // 析构函数 ~Student() { delete[] name; cout 析构函数执行释放姓名内存 endl; } void show() { cout 学号 id 姓名 name endl; } }; int main() { Student s1; s1.show(); Student s2(2026001, 小明); s2.show(); Student s3 s2; s3.show(); return 0; }五、核心总结面试 / 期末速记构造函数同名、无返回值创建对象自动调用支持重载分为无参、有参、拷贝构造初始化列表优先用于成员初始化处理 const / 引用作用初始化对象成员。析构函数~类名无参无返回值只能一个对象销毁自动调用负责释放堆、文件等资源堆对象不 delete 则析构不执行造成内存泄漏有堆指针成员必须手动写析构释放内存。高频易错点写了有参构造无法直接Person p;缺少无参构造浅拷贝导致析构重复释放内存程序崩溃忘记释放堆内存引发内存泄漏混淆调用时机构造在创建时析构在销毁时。结尾构造和析构是 C 面向对象的基础核心也是内存管理的第一道关卡。理解两者的调用时机、语法规则、资源处理逻辑才能避开深浅拷贝、内存泄漏等经典 bug。后续学习继承、多态时派生类构造析构的执行顺序也建立在本节基础之上。