构造函数需无返回类型、名同类名、不可用virtual/static/const修饰;析构函数在对象生命周期结束时自动调用,用于清理资源而非释放内存,有虚函数的类应声明虚析构函数。

构造函数怎么写才不会报错
构造函数不是普通函数,它没有返回类型(连 void 都不能写),名字必须和类名完全一致,且不能被 virtual、static 或 const 修饰。
常见错误现象:error: constructor cannot be declared 'virtual'、error: return type specified for constructor。
- 如果类里没写任何构造函数,编译器会自动生成一个无参、空体的默认构造函数;但只要写了任意一个构造函数,这个自动生成就没了
- 想同时支持无参和带参初始化,得显式写两个:
A()和A(int x),否则A a;会编译失败 - 推荐用委托构造(C++11 起)避免重复逻辑:
A() : A(0) {},注意冒号后是调用另一个构造函数,不是函数调用语句 - 初始化列表比在函数体内赋值更高效,尤其对 const 成员、引用成员或没有默认构造函数的类类型成员——它们只能在初始化列表里“出生”时被赋予初值
析构函数什么时候会被调用
析构函数的作用不是“释放内存”,而是“清理资源”。它在对象生命周期结束时自动调用:局部对象出作用域、delete 动态分配的对象、临时对象绑定到 const 引用结束后(除非延长了生命周期)。
典型误用:delete this; 在析构函数里调用,或者手动调用 obj.~A() —— 这些都会导致重复析构,大概率崩溃。
立即学习“C++免费学习笔记(深入)”;
- 析构函数必须是
public且非static的;如果类有虚函数,析构函数最好声明为virtual,否则通过基类指针删除派生类对象时,派生类部分不会被析构 - 不要在析构函数里抛异常(C++11 起默认是
noexcept),否则程序直接终止——因为栈展开过程中再抛异常是未定义行为 - 析构函数里别调用虚函数,此时虚表可能已被销毁,实际调用的是当前类(而非最终派生类)的版本
移动语义下构造/析构的调用顺序容易被忽略
当对象被移动(比如 std::vector 扩容时重新安置元素),移动构造函数和移动析构函数参与进来,但它们的行为和拷贝版完全不同:移动构造通常“掏空”源对象,而移动析构对已掏空的对象要能安全收尾。
- 移动构造函数参数是右值引用:
A(A&& other),内部常做指针交换、置空操作,不 new/malloc 新资源 - 对应地,析构函数必须能处理“内部指针为
nullptr”的状态,否则delete nullptr虽安全,但delete ptr前不判空就危险 - 若类管理文件描述符、socket、mutex 等系统资源,移动后原对象应标记为“已转移”,析构时跳过关闭逻辑;否则双关、死锁、段错误都可能发生
double free 或 use-after-free 就藏在看似正常的调用链里。









