构造函数与析构函数的显示调用

目录

前言:

构造函数的显示调用

显示调用无参构造

隐式调用无参构造

显示调用有参构造

构造函数的执行顺序 

析构函数的显示调用

析构函数的调用顺序

显示调用析构函数


前言:

构造函数是类的特殊成员函数,创建对象时编译器会自动调用构造函数

析构函数是类的特殊成员函数,当对象的生命周期结束时,编译器自动隐式调用析构函数

构造函数的显示调用

构造函数按照参数类型可以分为有参构造无参构造,调用构造函数的方式分别为显示调用隐式调用

显示调用无参构造

class Date
{
public:
	//构造函数函数名与类名相同且无返回值
	//无参构造
	Date()
	{
		cout << "调用构造函数" << endl;
	}
private:
	int _year = 2024;
	int _month = 3;
	int _day = 1;
};
int main()
{
	//显示调用
	Date d = Date();
	return 0;
}

监视窗口:

运行窗口:

注:构造函数调用时先执行初始化列表的位置,在执行函数体中的语句;

隐式调用无参构造

class Date
{
public:
	//构造函数函数名与类名相同且无返回值
	//无参构造
	Date()
	{
		cout << "调用构造函数" << endl;
	}
private:
	int _year = 2024;
	int _month = 3;
	int _day = 1;
};
int main()
{
	//隐式调用
	Date d;
	return 0;
}

监视窗口:

运行窗口:

显示调用有参构造

class Date
{
public:
	//构造函数函数名与类名相同且无返回值
	//有参构造
	Date(int year,int month,int day)
		: _year(year)
		, _month(month)
		, _day(day)
	{
		cout << "调用构造函数" << endl;
	}
private:
	int _year = 2024;
	int _month = 3;
	int _day = 1;
};
int main()
{
	//显式调用
	Date d(2024, 3, 15);
	return 0;
}

监视窗口:

运行窗口:

总结:

  • 一般情况下默认的无参构造函数自动地隐式调用
  • 有参构造函数是由开发者手动地显示调用

构造函数的执行顺序 

class A
{
public:
	A()
	{
		cout << "调用A类的构造函数" << endl;
	}
private:
	int _a = 1;
};

class B
{
public:
	B()
	{
		cout << "调用B类的构造函数" << endl;
	}
private:
	int _b = 2;
};

class C
{
public:
	C()
	{
		cout << "调用C类的构造函数" << endl;
	}
private:
	int _c = 3;
};

class D
{
public:
	D()
	{
		cout << "调用D类的构造函数" << endl;
	}
private:
	int _d = 4;
};

C c;//全局对象
int main()
{
	A a;
	B b;
	static D d;//静态对象
	return 0;
}

运行结果:

构造函数:定义对象时进行调用;

析构函数的显示调用

析构函数的调用顺序

class A
{
public:
	~A()
	{
		cout << "调用A类的析构函数" << endl;
	}
private:
	int _a = 1;
};

class B
{
public:
	~B()
	{
		cout << "调用B类的析构函数" << endl;
	}
private:
	int _b = 2;
};

class C
{
public:
	~C()
	{
		cout << "调用C类的析构函数" << endl;
	}
private:
	int _c = 3;
};
class D
{
public:
	~D()
	{
		cout << "调用D类的析构函数" << endl;
	}
private:
	int _d = 4;
};

C c;//全局对象
int main()
{
	A a;//局部对象
	B b;//局部对象
	static D d;//静态对象
	return 0;
}

运行结果:

监视窗口:

  1. 局部对象的析构顺序与构造顺序相反,由于局部对象存放于栈区,栈区高地址处存放对象a,低地址处存放对象b(栈区使用习惯先使用高地址,再使用低地址),析构时先销毁低地址处的局部对象,后销毁高地址处的局部对象;
  2. static修饰的静态对象存放于静态区,对象生存的作用域(main()函数内部)结束时销毁;
  3. 程序结束时销毁全局对象;

显示调用析构函数

class Test
{
public:
	Test()
	{
		cout << "调用构造函数" << endl;
	}
	~Test()
	{
		cout << "调用析构函数" << endl;
	}
private:
	int _a;
};

int main()
{
	Test t;
	t.~Test();//显示调用析构函数
	return 0;
}

运行结果:

开发者创建的对象通常在语句体{ }中,当语句体{ }结束时该对象被销毁,但是这种对象通常存放于栈区这就意味着如何管理此对象,是由操作系统完成而开发者无法控制;所以即使开发者显示调用析构函数,当对象的生命周期结束时,操作系统依然会再次调用析构函数,将其在栈区销毁,实现真正的析构

class Test
{
public:
	Test()
	{
		cout << "调用构造函数" << endl;
		_a = new int[10];//堆区申请空间
	}
	~Test()
	{
		cout << "调用析构函数" << endl;
		delete[] _a;//释放堆区开辟的空间
	}
private:
	int* _a;
};

int main()
{
	Test t;
	t.~Test();
	return 0;
}

运行结果:

一旦析构函数中存在释放堆空间的语句,第二次调用析构函数会释放已经释放的空间,导致系统崩溃;

第一次显示调用析构函数,相当于调用一个普通的成员函数,执行函数体内的语句,释放了堆内存,但是并未释放栈内存对象还存在

第二次操作系统调用析构函数,再次释放堆内存,造成系统崩溃,然后真正释放栈内存,销毁对象

  • 19
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小呆瓜历险记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值