C++学习之路(三)

本文介绍了C++中的对象初始化和清理,重点讲解了构造函数和析构函数的作用,以及它们在对象生命周期中的自动调用。内容涵盖构造函数的分类、调用规则、深拷贝与浅拷贝的概念,以及初始化列表、explicit关键字和new运算符的使用。此外,还讨论了动态内存分配中的问题和解决方案。
摘要由CSDN通过智能技术生成

对象的初始化和清理

具体来说,当我们创建对象的时候,这个对象应该有一个初始状态,当对象销毁之前应该销毁自己创建的一些数据。
对象的初始化和清理也是两个非常重要的安全问题,一个对象或者变量没有初始时,对其使用后果是未知,同样的使用完一个变量,没有及时清理,也会造成一定的安全问题。c++为了给我们提供这种问题的解决方案,构造函数和析构函数,这两个函数将会被编译器自动调用,完成对象初始化和对象清理工作。
无论你是否喜欢,对象的初始化和清理工作是编译器强制我们要做的事情,即使你不提供初始化操作和清理操作,编译器也会给你增加默认的操作,只是这个默认初始化操作不会做任何事,(函数体是空的)所以编写类就应该顺便提供初始化函数。
为什么初始化操作是自动调用而不是手动调用?既然是必须操作,那么自动调用会更好,如果靠程序员自觉,那么就会存在遗漏初始化的情况出现。

构造函数和析构函数

构造函数

类的构造函数是类的一种特殊的成员函数,它会在每次创建类的新对象时执行。
构造函数的名称与类的名称是完全相同的,并且不会返回任何类型,也不会返回 void。构造函数可用于为某些成员变量设置初始值。

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

class Person
{
   
public:
	//构造函数写法
	//与类名相同,没有返回值 ,不写void,可以发生重载 (可以有参数)
	//构造函数由编译器自动调用,而不是手动,而且只会调用一次
	Person()
	{
   
		cout << "构造函数调用" << endl;
	}

	Person(int a)
	{
   
		cout << "构造函数调用(int a)" << endl;
	}


	//析构函数写法
	// 与类名相同 类名前面加一个符号 “~” ,也没有返回值 ,不写void, 不可以有参数(不能发生重载)
	//自动调用,只会调用一次
	~Person()
	{
   
		cout << "析构函数调用" << endl;
	}


};
void test01()
{
   
	Person p1(1); //默认调用了构造和析构,是系统提供的两个空实现的函数
}

int main(){
   
	test01();
	system("pause");
	return EXIT_SUCCESS;
}

构造函数的分类及调用

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;

//分类
//按照参数进行分类  无参构造函数(默认构造函数)   有参构造函数
//按照类型进行分类  普通构造函数  拷贝构造函数
class Person
{
   
public: //构造和析构必须写在public下才可以调用到

	Person() //默认 、 无参构造函数
	{
   
		cout << "默认构造函数调用" << endl;
	}

	Person(int a)
	{
   
		cout << "有参构造函数调用" << endl;
	}

	//拷贝构造函数
	Person(const Person& p)
	{
   
	    //p.m_Age=100  没有const的话p1的年龄就会被修改。
		m_Age = p.m_Age;
		cout << "拷贝构造函数调用" << endl;
	}

	~Person()
	{
   
		cout << "析构函数调用" << endl;
	}

	int m_Age;
};


void test01()
{
   
	//构造函数调用方式
	//括号法调用
	//Person p1(1); //有参
	//p1.m_Age = 10;
	//Person p2(p1); //拷贝  p2将p1中的数据拷贝走
	//cout << "p2的年龄" << p2.m_Age << endl;最后有两个   析构函数调用

	//Person p3; //默认构造函数 不要加()   Person p3(); //编译器认为这行是函数的声明


	//显示法调用
	//Person p4 = Person(100);将匿名对象起名为p4
	//Person p5 = Person(p4);

	//Person(100); //叫匿名对象 ,匿名对象特点,如果编译器发现了对象是匿名的,那么在这行代码结束后就释放这个对象

	//不能用拷贝构造函数 初始化匿名对象
	//Person(p5);如果这么写,编译器会认为你写成Person p5;error:"Person p5重定义"对象的声明。如果写成右值,那么可以。
	//Person p6 = Person(p5); //如果写成左值,编译器认为你写成 Person p5; 对象的声明,如果写成右值,那么可以

	
	Person p7 = 100; //相当于调用了 Person p7 = Person(100) ,隐式类型转换
	Person p8 = p7; // 相当于  Person p8 = Person(p7);
}


int main(){
   

	test01();

	system("pause");
	return EXIT_SUCCESS;
}

拷贝构造函数调用时机

1.对象以值传递的方式传给函数参数
2.用一个对象初始化另一个对象
3.函数局部对象以值传递的方式从函数返回(vs debug模式下调用一次拷贝构造,qt不调用任何构造)

class Person{
   
public:
	Person(){
   
		cout << "no param contructor!" << endl;
		mAge = 10;
	}
	Person(int age){
   
		cout << "param constructor!" << endl;
		mAge = age;
	}
	Person(const Person& person){
   
		cout << "copy constructor!" << endl;
		mAge = person.mAge;
	}
	~Person(){
   
		cout << "destructor!" << endl;
	}
public:
	int mAge;
};
//1. 旧对象初始化新对象
void 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值