C++学习笔记之对象构造&析构的理解

一、类声明

类的声明和实现是分开做的,在头文件中生命类的属性和函数,在cpp文件中实现函数具体业务。

Teacher.h

#pragma once
class Teacher
{
private:
	char name[20];
	int age;
public:
	void setAge(int _age);
	int getAge();
	
};

Teacher.cpp

#include "Teacher.h"

void Teacher::setAge(int _age) {
	age = _age;
}

int Teacher::getAge() {
	return age;
}

当类中没有声明构造函数和复制构造函数,编译器会提供默认的空构造函数和默认的复制构造函数,提供的默认的构造函数只是浅拷贝,简单的成员变量复制。
当类中定义了复制构造函数后,编译器不在提供空构造函数。
当类中定义了有参构造函数后,编译器不在提供空构造函数。
当类中提供了构造函数或复制构造函数,编译器就不再提供空构造函数或默认的复制构造函数。
当类中提供了有参构造函数,C++编译器不再提供构造函数。

class Teacher
{
public:
	//....省略
	//复制构造
	Teacher(const Teacher& t) {
		cout << "Teacher 复制构造函数执行" << endl;
	}
};

int main() {
	Teacher teacher01(2);
	Teacher teacher02 = teacher01;
	cout << teacher02.age << endl;//打印:-858993460,重写了复制构造函数,但是没有其他操作,所以打印垃圾值
	
	system("pause");
	return 0;
}

但是如果不重写复制构造函数,编译器会帮我们实现复制构造函数,执行的结构就是teacher02.age = 2,且这里teacher02对象不会执行构造函数,只会执行他的复制构造函数。

二、构造函数

构造函数声明

对象创建时执行,先创建的对象先构造

//无参构造
Teacher();
//有参构造
Teacher(int a);
//复制构造函数(copy构造函数)
Teacher(const Teacher &teacher);

构造函数调用

class Teacher
{
public:
    int age;
	//无参构造
	Teacher() {
		cout << "Teacher 无参构造函数执行" << endl;
	}

	//有参构造
	Teacher(int a) {
		cout << "Teacher 有参构造函数执行 a : " << a << endl;
	}
};

int main() {
	//==================无参构造调用=======================
	Teacher teacher01;//打印结果:Teacher 无参构造函数执行

	//==================有参构造调用=======================
	//调用有参构造函数,这里的等号已经不是赋值运算,C++对等号功能进行了扩展
	Teacher teacher02 = 2;//打印结果:Teacher 有参构造函数执行 a : 2
	
	//等价Teacher teacher02 = 3。因为等号右侧是括号表达式,最后一个值是结果
	Teacher teacher03 = (2, 3);//打印结果:Teacher 有参构造函数执行 a : 3

	Teacher teacher04(4);//打印结果:Teacher 有参构造函数执行 a : 4

	system("pause");
	return 0;
}

三、copy构造函数

作用:用一个对象去初始化另一个对象。
复制构造函数声明:Teacher(const Teacher &teacher)

复制构造函数调用方式

方式一:

Teacher teacher01(2);
Teacher teacher02 = teacher01;

方式二:

Teacher teacher01(2);
Teacher teacher02(teacher01);//Teacher 复制构造函数执行

方式三:

void fun(Teacher t) {
	cout << "fun t.age : "<< t.age << endl;
}

int main() {
	Teacher teacher01(2);//打印结果:Teacher 有参构造函数执行 a : 2
	fun(teacher01);//打印结果:Teacher 复制构造函数执行
	system("pause");
	return 0;
}

fun函数调用时,会将teacher01拷贝一份复制给fun的参数,所以也会执行复制构造函数

方式四:

Teacher fun() {
	Teacher teacher01(2); 
	cout << "fun()函数创建teacher01对象" << endl;
	//用teacher01对象创建了一个匿名对象返回
	return teacher01;//fun函数执行完后teacher01对象释放
}

void test() {
	fun();//fun返回的匿名对象没有使用,所以当test函数执行完,匿名对象也要释放
	cout << "test()执行完毕" << endl;
}

int main() {
	test();
	system("pause");
	return 0;
}

打印结果:

Teacher 有参构造函数执行 a : 2
fun()函数创建teacher01对象
Teacher 复制构造函数执行
Teacher 析构构造函数执行
Teacher 析构构造函数执行
test()执行完毕

执行流程:

01.创建teacher01对象 >>> 02.将teacher01对象初始化一个匿名对象 >>> 03.fun函数执行结束后会释放teacher01对象 >>> 04.fun()函数返回值没有对象接受,所以也得释放匿名对象。

结论:函数返回的是一个元素(复杂类型),返回的是一个新的匿名对象,所以会调用匿名对象的类的复制构造函数。

如果fun()函数返回值有对象接受执行结果就不同了。

Teacher fun() {
	Teacher teacher01(2); 
	cout << "fun()函数创建teacher01对象" << endl;
	return teacher01;
}

void test() {
	Teacher teacher = fun();//teacher接受fun函数返回的匿名对象
	cout << "test()执行完毕" << endl;
}

int main() {
	test();
	system("pause");
	return 0;
}

fun()返回值由teacher对象接受,C++编译器直接把匿名对象转成teacher,从无名转成有名,所以此处没有执行复制构造函数,匿名对象在test函数执行完也会释放,打印结果对比如下图:
C++学习笔记之对象构造&析构的理解_第1张图片fun()返回值赋值给teacher对象,匿名对象会被释放,所以test函数执行完要多释放一个对象,打印结果对比如下图:
C++学习笔记之对象构造&析构的理解_第2张图片

备注:上面打印截图“赋值构造函数执行”写错了,应是“复制构造函数执行”。这里一定要分清楚复制和赋值的区别。

函数返回的匿名对象去留总结

  • 1.如果函数返回的匿名对象没有接收对象,那么匿名对象被析构;
  • 2.如果函数返回的匿名对象初始化给同类型的对象,匿名对象转成该同类型的有名对象(不会调用复制构造函数);
  • 3.如果函数返回的匿名对象赋值给同类型的对象,那么匿名对象被析构。

==的复制&赋值区别

“==”在不同的场景有不同的含义:

  • 1.一个是初始化执行复制构造函数
  • 2.一个简单的赋值
int main() {
	Teacher teacher01(2);//打印:Teacher 有参构造函数执行 a : 2

	//此处等号是用teacher01初始化teacher02
	Teacher teacher02 = teacher01;//打印:Teacher 复制构造函数执行

	Teacher teacher03(3);//打印:Teacher 有参构造函数执行 a : 3
	teacher03 = teacher01;//此处等号是将teacher01赋值给teacher03
	
	system("pause");
	return 0;
}

四、析构函数

对象销毁时执行,先创建的对象后析构

举例:
Teacher.h

class Teacher
{
private:
	char name[20];
	int age;
public:
	Teacher();//构造函数声明
	~Teacher();//析构函数
	void setAge(int _age);
	int getAge();
	
};

Teacher.cpp

void Teacher::setAge(int _age) {
	cout << "Teacher setAge函数执行" << endl;
	age = _age;
}

int Teacher::getAge() {
	cout << "Teacher getAge函数执行" << endl;
	return age;
}

Teacher::Teacher() {
	cout << "Teacher 构造函数执行" << endl;
}

Teacher::~Teacher() {
	cout << "Teacher 析构函数执行" << endl;
}

test.cpp

//teacher是一个局部变量,函数执行完就会释放
void objTest() {
	cout << "声明Teacher befor" << endl;
	Teacher teacher;
	cout << "声明Teacher after" << endl;
	teacher.setAge(10);
	cout << "age : " << teacher.getAge() << endl;//age : 10
}

int main() {
	objTest();
	system("pause");
	return 0;
}

执行结果

声明Teacher befor
Teacher 构造函数执行
声明Teacher after
Teacher setAge函数执行
Teacher getAge函数执行
age : 10
Teacher 析构函数执行

Teacher teacher生命对象的时候就会执行构造函数,在函数objTest()执行结束后teacher会释放内存,会执行析构函数。

五、struct&class区别

struct在C++中进行了加强,可以和class具有一样的功能。
默认struct访问权限是public,默认class访问权限是private

struct MyStruct
{
	int age;
};

class MyClass
{
	int age;
};

int main() {
	MyStruct mystr;
	MyClass cls;
	mystr.age = 20;//编译成功,默认struct访问权限是public
	cls.age = 20;//编译报错,默认class访问权限是private
	system("pause");
	return 0;
}

备注:代码自动格式化:Ctrl+K+F键(按住Ctrl键,先按下K键再按下F键)

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