请添加图片描述

前言

在C++中定义一个类时,会包含各种成员函数,它们各司其职,实现不同的功能,而构造函数析构函数就是其中两个必不可少的成员函数,分别负责初始化成员变量资源释放


1.构造函数

1.1.定义

在对象创建(实例化)时,初始化对象
:虽然名字叫构造函数,但它的功能不涉及开辟空间创建对象

1.2.特点

  1. 函数名与类名相同
  2. 无返回值
  3. 对象实例化时会自动调用相应的构造函数
  4. 可以重载(参数数量、类型发生改变)
  5. 如果类中没有显式定义构造函数,那么编译器会自动生成一个默认的无参构造函数
  6. 无参构造函数、全缺省构造函数和编译器默认生成的构造函数,都叫做默认构造函数(只能有一个存在,不能同时存在)
  7. 编译器默认生成的构造函数中,内置类型成员变量是否初始化是不确定的,要看编译器;而自定义类型的成员变量,会调用它自己的默认构造函数进行初始化

1.3.代码实例

#include <iostream>
using namespace std;
//定义日期类
class Date{
public:
    // 1.无参构造函数
    Date(){
        _year = 1;
        _month = 1;
        _day = 1;
    }
    // 2.带参构造函数
    Date(int y, int m, int d){
        _year = y;
        _month = m;
        _day = d;
    }
    // 3.全缺省构造函数
    /*
     Date(int y = 1, int m = 1, int d = 1){
        _year = y;
        _month = m;
        _day = d;
    }
    */
    void print(){
        cout << _year << "-" << _month << "-" << _day << endl;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main() {
    Date d1; //调用默认构造函数
    Date d2(2025, 9, 9); //调用带参构造函数
    //Date d3(); //编译无法通过
    d1.print();
    d2.print();
    //d3.print();
    return 0;
}

2.析构函数

2.1.定义

在对象销毁(生命周期结束)时,自动调用,完成对资源的清理和释放工作
:析构函数不是完成对对象本身的销毁(局部对象存在栈帧,调用结束后会自动释放),如果没有资源的释放,实际上就不需要析构函数

2.2.特点

  1. 析构函数名是在类名前加上
  2. 无参数无返回值
  3. 一个类只能有唯一一个析构函数,如果没有显示定义,则会生成一个默认的析构函数
  4. 在对象声明周期结束时,自动调用
  5. 编译器自动生成的析构函数,对内置类型成员不做处理,自定义类型成员会调用它自己的析构函数
  6. 显式写析构函数时,自定义类型成员仍然会调用它自己的析构函数(自定义类型成员无论什么情况都会自动调用析构函数)
  7. 如果类中没有资源申请或默认的析构函数就可以用时,可以不写析构函数,直接用默认的析构函数;有资源申请时,一定要写析构函数,否则会造成内存泄漏
  8. 一个局部域的多个对象,先定义的后析构

2.3.代码实例

//栈的类
typedef int DataType;
class Stack{
public:
    Stack(int n = 4){
        _a = (DataType*)malloc(sizeof(DataType) * n);
        if(_a == nullptr){
            perror("Malloc Failed!");
            return;
        }
        _capacity = n;
        _top = 0;
    }
    
    ~Stack(){
        cout << "~Stack()" << endl;
        free(_a);
        _a = nullptr;
        _capacity = _top = 0;
    }
private:
    DataType* _a;
    size_t _capacity;
    size_t _top;
};

//借助两个栈实现队列
class MyQueue{
public:
    //······
    //编译器默认生成的析构函数会自动调用两个成员相应的析构函数,因此不用再显式定义析构函数了
private:
    Stack pushSt;
    Stack popSt;
};

更多推荐