#拷贝构造

目录

1.引入

2.拷贝构造函数的定义

3.特征

4.编译器自动生成拷贝构造函数


1.引入

C语言的拷贝,直接传值,值拷贝

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2024, 4, 26);
	d1.print();
	Date d2(d1);//直接传值
	d2.print();
	return 0;
}

但是如果只是一个堆类呢(自定义类型),直接传值会发生什么?

class Date
{
public:
	Date(int year = 1, int month = 1, int day = 1)
	{
		_year = year;
		_month = month;
		_day = day;
	}
	void print()
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}
private:
	int _year;
	int _month;
	int _day;
};
class Stack
{
public:
	Stack(int n = 4)
	{
		if (n == 0)
		{
			a = nullptr;
			top = capacity = 0;
		}
		else
		{
			a = (int*)malloc(sizeof(int) * n);
			if (a == nullptr)
			{
				perror("malloc fail");
				exit(-1);
			}
			capacity = n;
			top = 0;
		}
	}
	~Stack()
	{
		if (a)
		{
			free(a);
			a = NULL;
			capacity = 0;
			top = 0;
		}
	}
private:
	int* a;
	int capacity;
	int  top;
};
int main()
{
	Stack s1(10);
	Stack s2(s1);
	return 0;
}

编译器会报错,为什么呢?

因为Stack类(自定义类型)里面有指针,将s1里面a的地址,传给了s2里面的a,即s1里面的a与s2里面的a指向的是同一块空间,在调用完s2之后,s2里面的a就被编译器自动调用的析构函数释放了,那调用完s2之后,又会去调用析构函数对s1里面的a指向的空间进行释放,相当于会对同一块空间释放两次,同时,s1里面的a在s2里面的a释放之后又变成了野指针,这当然是不行的。

C++规定自定义类型传值传参必须用拷贝构造函数去完成

2.拷贝构造函数的定义

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新对象时由编译器自动调用

3.特征

拷贝构造函数也是默认的成员函数,其特征如下:

1. 拷贝构造函数是构造函数的一个重载形式

2. 拷贝构造函数的参数只有一个且必须是类类型对象的引用,使用传值方式编译器直接报错, 因为会引发无穷递归调用

3. 若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按,字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝。

一个拷贝构造函数的案例

4.编译器自动生成拷贝构造函数

如果我们不写拷贝构造函数,编译器会自动生成,自动生成的拷贝构造函数的特点

1.内置类型,值拷贝

2.自定义类型,去调用我们自己写的它的拷贝构造函数。

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请 时,则拷贝构造函数是一定要写的,否则就是浅拷贝。

5. 拷贝构造函数典型调用场景

1.使用已存在对象创建新对象

2.函数参数类型为类类型对象

使用已存在对象创建新对象案例,注意这里有两种写法都可以

函数参数类型为类类型对象案例,对下面的代码进行调试,你会发现有拷贝构造函数的调用。

class Date
{
public:
	Date(int year=1, int month=1, int day=1)
	{
		this->_day = day;
		this->_month = month;
		this->_year = year;
	}
	Date(const Date& d)
	{
		this->_day = d._day;
		this->_month = d._month;
		this->_year = d._year;
	}
private:
	int _year;
	int _month;
	int _day;
};
 void Test(Date d)//函数的参数为类类型
{
	 cout << "Test()" << endl;
}
int main()
{
	Date d1(2022, 1, 13);
	Test(d1);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值