构造、析构、拷贝构造及赋值运算符重载——知识小结

文章详细解释了C++中构造函数、析构函数、拷贝构造函数和赋值运算符的使用,强调了对象初始化和析构的顺序规则,以及传引用参数和返回的优势。还通过实例说明了Date、Stack、MyQueue等类在这些方面的行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

//                                                                         (1)大部分的类都需要自己写构造函数  (2)只有像MyQueue这样的类不需要显示构造函数
//                                             构造函数主要完成初始化工作 (3)每个类最好都要提供 默认构造函数(无需传参)。                      
//                         初始化和清理
// 
//                                             析构函数主要完成清理工作   (1)一些类需要显示写析构函数。比如:Stack\Queue....;  (2)一些类不需要显示写析构函数。a\ 比如Date这样类,没有资源需要清理。 
//                                                                          b\ 比如MyQueue这样的类也可以不写,默认生成的就可以了。
//                                                                        (3)析构的顺序:先定义的,后析构; 后定义的,先析构。
//  
// 
//                                          拷贝构造是使用同类对象初始化创建对象  
// 6个默认成员函数          拷贝复制                                                   (1)一些类需要显示写拷贝和赋值。比如:Stack\Queue....
//                                                                                     (2)一些类不需要显示写拷贝和赋值。A、比如像Date这样的类,默认生成就会完成值拷贝或浅拷贝 
//                                                                                       B、比如MyQueue这样的类,默认生成就会调用他的自定义类型成员 Stack的拷贝和赋值。                                         
//                                          赋值重载主要是把一个对象赋值给另一个对象
//
// 
//
//                         取地址重载          主要是普通对象和 const对象取地址,这两个很少会自己实现
//
//
//
//               构造函数        析构函数        拷贝构造函数       赋值运算符重载
//
// Date类          √              ×                ×                 ×
//
//
// Stack类         √             √                √                  √
//
//
// MyQueue类       ×             ×                ×                  ×


1、存储在不同区域对象的初始化和析构的顺序

//函数栈帧和栈区(内存)内对象都要符合后进先出,也就是后定义先销毁/析构。
//(1)局部的对象(在栈区内)的析构顺序(先定义,后析构;后定义,先析构)
//(2)全局的对象(在静态区)在调用main函数之前就初始化了
//(3)静态的对象(在静态区)在首次调用的时候进行初始化(后面就不再进行初始化了)[同类型的静态变量,也遵循 先定义,后析构;后定义,先析构 ]
//(4)全局的对象和静态的对象都是在工程结束时才进行析构的。(所以最后析构)



#include <iostream>
using namespace std;

class A
{
public:
	A(int a=0) //A(this,int a=0)
	{
		this->_a = a;
		cout<< "A(int a=0)->" << _a << endl;
	}

	~A() // ~A(this)
	{
		cout<< "~A()->" << this->_a << endl;
	}

private:
	int _a;
};

A aa3(3); // 全局的对象(在静态区)在调用main函数之前就初始化了

void Func()
{
	static A aa0(0);  // 静态的对象(在静态区)在首次调用的时候进行初始化(后面就不再进行初始化了)
	A aa1(1); // A aa1(&aa1,1);
	A aa2(2);
	static A aa4(4);

}

int main()
{
	Func();
	Func();

	return 0;
}

2、传引用传参和传引用返回(拷贝构造函数)

2.1 传引用传参

class A
{
public:
	//构造函数
	A(int a)
	{
		_a = a;
		cout<< "A(int a)->" << _a << endl;
	}

	//拷贝构造函数
	A(const A& a)
	{
		_a = a._a;
	    cout << "A(const A& a)->" << _a << endl;
	}

	//析构函数
	~A()
	{
		cout<< "~A()->" << _a << endl;
	}


private:
    int _a;
};

void Func1(A a)
{
	cout<< "Func1" << endl;
}

void Func2(A& a)
{
	cout << "Func2" << endl;
}

int main()
{
	A a1(1);

	//Func1(a1);
	Func2(a1);   //结论:针对于 自定义类型的对象而言,传引用传参比传值传参更具有优势,不需要拷贝构造,提高了效率。
	             // 对于内置类型变量而言,传值传参是对变量的临时拷贝,而传引用传参从底层分析也是开辟了四个字节的地址(创建指针)。
	
	return 0;
}

2.2 传引用返回

class A
{
public:
	//构造函数
	A(int a)
	{
		_a = a;
		cout << "A(int a)->" << _a << endl;
	}

	//拷贝构造函数
	A(const A& a)
	{
		_a = a._a;
		cout << "A(const A& a)->" << _a << endl;
	}

	//析构函数
	~A()
	{
		cout << "~A()->" << _a << endl;
	}

private:
	int _a;
};

A Func3()
{
	A a3(3);
	return a3; //传值返回,返回的是a3的拷贝aa3 ,aa3在Func3()销毁之前还要析构。
}

A& Func4()
{
	static A a4(4);
	return a4; //传引用返回,返回的是a4的别名aa4。{需要注意的是,如果a4出了Func4()的作用域就销毁了,那么引用返回是有问题的}
			   //相比于传值返回,传引用返回不需要额外拷贝一次对象,也不需要再析构一次拷贝的对象。
}

int main()
{
	Func3();
	cout << endl;
	Func4();

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值