析构函数和delete区别
析构函数:
析构函数没有参数,没有返回值,不能重载;
理解:在创建对象时,系统会自动调用构造函数进行初始化,这样需要申请内存,同样在程序结束时,或者需要销毁对象时,程序也会自动调用一个函数来进行清理工作;
一个类只能有一个析构函数,很多时候都是系统隐式调用对对象进行销毁,程序员也无法显式调用,(但可以在析构函数里写上自己想要在销毁的时候需要进行的别的工作,比如:
/用来计数雇员数量程序/
Employee(std::string name, Gender gender, Date birthday) :name{ name }, gender{ gender }{
this->birthday=new Date{ birthday };
//默认构造函数,自增
numberofObjects++;
std::cout << “Now there are :” << numberofObjects << “employees” << std::endl;
}
//析构函数
~Employee() {
numberofObjects–; //进行自减
std::cout << birthday->to_string() << std::endl;
delete birthday; //归还内存
birthday = nullptr;
std::cout << “Now there are :” << numberofObjects << " employees" << std::endl;
}
析构函数被调用及delete的区别
(以下知识点引用自区柒大人)
在所有函数之外创建的对象为全局对象,与全局变量类似,位于内存分区的全局数据区,程序在结束时,会调用这些对象的析构函数。
在函数内部创建的对象是局域对象,它与局部变量类似,位于栈区,函数结束时会调用它们的析构函数;
而new创建的对象位于堆区,在通过delete删除时才会调用析构函数;如果没有delete,则析构函数就不会被调用。
例子:
###Employee.h#####
enum class Gender
{
male,
female,
};
class Employee
{
private:
std::string name;
Gender gender;
Date* birthday; //任务2:变成指针,此为指向对象的指针,所以需要new出来一个对象,把指针指向它
static int numberofObjects; //任务1:增加静态成员,计算雇员数量
public:
void setName(std::string name) { this->name = name; }
void setGender(Gender gender) { this->gender = gender; }
void setDate(Date birthday) { *this->birthday = birthday; }
std::string getName() { return name; }
Gender getGender() { return gender; }
Date getBirthday() { return *birthday; }
std::string to_String() {
return (name + " "+ (gender == Gender::male ? std::string("male") : std::string("female")) +" "+ birthday->to_string());
} //对指针进行引用时用箭头运算符,实体类型用点
Employee(std::string name, Gender gender, Date birthday) :name{ name }, gender{ gender }
{
this->birthday=new Date{ birthday };
//默认构造函数,自增
numberofObjects++;
std::cout << "Now there are :" << numberofObjects << "employees"<< std::endl;
}
Employee():Employee(“Alan”,Gender::male,Date(2020,01,28)){}
//析构函数
~Employee()
{
numberofObjects–; //减法
std::cout << birthday->to_string() << std::endl;
delete birthday; //归还内存
birthday = nullptr;
std::cout << “Now there are :” << numberofObjects << " employees" << std::endl;
}
###Date.h####
class Date {
private:
int year = 2019, month = 9, day = 1;
public:
int getYear() { return year; }
int getMonth() { return month;}
int getDay() { return day; }
void setYear(int y) { year = y; }
void setMonth(int m) { month = m; }
void setDay(int d) { day = d; }
Date() = default;
Date(int y, int m, int d) :year{ y }, month{ m }, day{ d }{
std::cout << "Date is " << to_string() <<std::endl; }
std::string to_string() {
return (std::to_string(year) + "-" + std::to_string(month) + "-" + std::to_string(day));
}
};
#####main.cpp##
#include
#include"Date.h"
#include"Employee.h"
int Employee::numberofObjects=0;
Employee a1{ “Karry”,Gender::male,Date(1999,9,21) }; //全局对象
int main() {
std::cout << a1.to_String() << std::endl;
std::cout << “\n” << std::endl;
Employee e1; //局部对象
std::cout << e1.to_String() << std::endl;
std::cout << “\n” << std::endl;
Employee* e2 = new Employee{ "WYB",Gender::female,Date(2001,02,26) }; //new出来的对象
std::cout << e2->to_String() << std::endl;
std::cout << "\n" << std::endl;
{
Employee e3{ "JackSon",Gender::male,Date(2000,11,28) }; //局部对象
std::cout << e3.to_String() << std::endl;
std::cout << "\n" << std::endl;
}
return (0);
}
解释:
- Employee a1 为全局对象,存在全局数据区;所以最后程序会调用它的析构函数
- Employee e1 为局部对象;e3也为局部对象,存在栈区,最后都会调用它们的析构函数
- Employee e2为new出来的对象,存在堆区,必须要delete才可以调用其析构函数
程序执行结果如下:
个人解释:
本人是小白,第一次写博客,帮助自己理清一些知识,这里会借用前人的一些解释,如果有什么错误,问题的话欢迎指出呀!