类与对象----析构函数

类与对象----析构函数

  • 1、析构函数的概念
  • 2、析构函数的特性
  • 3、当我们不写,编译器自动生成的默认析构函数
  • 4、析构函数的总结(对象生命周期结束后,C++编译器会自动调用析构函数)

1、析构函数的概念

//析构函数:与构造函数的功能相反,析构函数不是完成对对象本身的销毁(局部对象销毁工作是由编译器完成的),
//而是完成对象中资源的清理工作(对象在销毁时会自动调用析构函数)。

2、析构函数的特性

//析构函数是特殊的成员函数,其特征如下:
//(1)析构函数名是在类名前加上字符 ~(按位取反) 
//(2)无参数无返回值类型。
//(3)一个类只能有一个析构函数(无法重载)。如果我们没写析构函数,系统就会自动生成 默认析构函数。
//(4)对象生命周期结束时,编译器系统会自动调用析构函数。

//补充:自动调用构造函数和析构函数的优势:
// Stack st;
// StackInit(&st); ------ Stack st; {  实例化对象st时,就会自动调用构造函数进行初始化,不需要再额外调用StackInit(&st)了  }
//
//  bool ret = StackEmpty(&st);
//  StackDestroy(&st);      ---------- return st.Empty(); { 出了作用域(return之后),st自动调用析构函数进行清理,不要额外调用StackDestroy(&st)了 } 
//  return ret;
#include 
#include 
using namespace std;

//日期类
class Data
{
public:
	//全缺省构造函数
	Data(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}

	~Data() // ~Data()没有什么需要清理的,所以不需要写 (由编译器默认生成析构函数,也没清理什么)
	{
		cout << "~Data()" << endl;
	}

private:
	int _year;
	int _month;
	int _day;
};

//Stack类
typedef int DataType;
class Stack
{
public:
	Stack(int capacity = 3)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		assert(_array);

		_capacity = capacity;
		_size = 0;
	}

	~Stack() //~Stack()需要清理malloc出的空间,所以需要自己写 {对象中有 动态开辟的资源,最后需要手动释放的,需要自己写构造函数(因为在这种情况下默认生成的析构函数无法完成清理)}
	{
		free(_array);
		_array = nullptr;
		_capacity = _size = 0;
	}

private:
	DataType* _array;
	int _capacity;
	int _size;
};

void Func()
{
	Data d;
	Stack st1;

}

int main()
{
	Func();

	return 0;
}

3、当我们不写,编译器自动生成的默认析构函数

// 与构造函数类似:a\ 内置类型成员变量不处理(无法正确判断,无法处理。例如指针,到底是动态开辟的,还是fopen的,或者是6出来的)。 b\ 自定义类型成员变量会去调用它的析构函数。

//Stack类
typedef int DataType;
class Stack
{
public:
	Stack(int capacity = 3)
	{
		_array = (DataType*)malloc(sizeof(DataType) * capacity);
		assert(_array);

		_capacity = capacity;
		_size = 0;
	}

	~Stack()
	{
		free(_array);
		_array = nullptr;
		_capacity = _size = 0;
	}

private:
	DataType* _array;
	int _capacity;
	int _size;
};

//MyQueue类
class MyQueue
{
public:
	void push(int x) {}
	//...

	//MyQueue类里没有写析构函数,但是MyQueue类里默认生成的析构函数会让 自定义类型成员变量 去调用它的析构函数,不处理内置类型成员变量
private:
	size_t _size = 0; //内置类型成员变量不处理,但是加了缺省值
	Stack _st1;      //自定义类型成员变量会处理
	Stack _st2;
};

void Func()
{
	MyQueue q1;
}

int main()
{
	Func();

	return 0;
}

4、析构函数的总结(对象生命周期结束后,C++编译器会自动调用析构函数)

//分析思路:需不需要写析构函数:如果不写,系统自动生成的默认析构函数能否处理;如果默认析构函数无法处理,则就要写。

//(1)需要写(默认析构函数无法处理)。动态开辟的资源存储在内置类型成员中的,如果不写析构函数,
// 默认析构函数无法对内置类型成员变量处理,就会造成内存泄露。例如:Stack\Queue\List\SeqList\BinaryTree 。

// (2) 不需要写。(默认析构函数可以处理)
//A 日期类(没有类的资源需要清理)。默认析构函数就可以处理,但是没做什么。
//B 默认生成的析构函数就够用了。默认析构函数对于Stack自定义类型成员,调用Stack析构函数。

你可能感兴趣的:(c++)