类和对象——默认成员函数--拷贝构造函数

本文介绍了C++中的拷贝构造函数,包括它的概念和特征。拷贝构造函数在创建新对象时由编译器自动调用,用于复制已有对象。其特点包括:作为构造函数的重载形式,参数为类类型对象的引用,通常用const修饰。如果没有自定义拷贝构造函数,编译器会提供默认的浅拷贝,可能导致潜在的问题,如内存泄漏或野指针。因此,当类中涉及资源申请时,应自定义深拷贝构造函数以避免这些问题。

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

拷贝构造函数概念

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

拷贝构造函数的特征

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

void Fun1(Date d)
{

}
void Fun2(Date& d)
{

}
int main()
{
	Date d1(2022, 9, 22);
	Fun1(d1);
	Fun2(d1);
}

Fun1函数的形参只是实参的一个拷贝。(Date d(d1))会不断的调用拷贝构造,在传值的时候,编译器就直接禁掉了,报错。
Fun2函数的形参是实参的别名。
虽然传指针也是可以的,但是没有引用方便,况且规定也是参数要用引用;

内置类型是没有拷贝构造的概念的,自定义类型是有的。(因为编译器对内置知根知底,按字节拷没啥问题,但是对自定义的类型较为复杂的就是需要用函数来指示);

当然引用参数最好前面加一个const,防止拷贝的时候写反了,就有可能会把原来引用变量的数据给改了,所以加个const 把权限缩小一下,由写反的情况就会报错检查出来了。

3.如果没有显式的定义拷贝构造函数,编译就生成会默认的拷贝构造函数。
默认的拷贝构造函数,对内置的类型是按字节的方式直接拷贝的(类似memcpy),而自定义类型是调用其拷贝构造函数完成拷贝的。

class Time
{
  public:
	Time()
	{
		_hour = 1;
		_minute = 1;
		_second = 1;
		
	}
	Time(const Time& t)
	{
		_hour = t._hour;
		_minute = t._minute;
		_second = t._second;
		cout << "Time::Time(const Time&)" << endl;
	}
  private:
	int _hour;
	int _minute;
	int _second;
};
class Date
{
 private:
	// 基本类型(内置类型)
	int _year = 1970;
	int _month = 1;
	int _day = 1;
	// 自定义类型
	Time _t;
};
int main()
{
	Date d1;
		Date d2(d1);
	return 0;
}

在这里插入图片描述
首先是d1的构造,后来是d2的拷贝构造,但是Date类没有显式写拷贝构造,所以默认生成一个拷贝构造,对于内置的年月日都是直接字节拷贝,但是对于自定义的Time,就是去调用Time的拷贝构造。

typedef int DataType;
class Stack
{
public:
	Stack(size_t capacity = 10)
	{
		_array = (DataType*)malloc(capacity * sizeof(DataType));
		if (nullptr == _array)
		{
			perror("malloc申请空间失败");
			return;
		}
		_size = 0;
		_capacity = capacity;
	}
	void Push(const DataType& data)
	{
		// CheckCapacity();
		_array[_size] = data;
		_size++;
	}
	~Stack()
	{
		if (_array)
		{
			free(_array);
			_array = nullptr;
			_capacity = 0;
			_size = 0;
		}
	}
private:
	DataType* _array;
	size_t _size;
	size_t _capacity;
};
int main()
{
	Stack s1;
	s1.Push(1);
	s1.Push(2);
	s1.Push(3);
	s1.Push(4);
	Stack s2(s1);
	return 0;
}

首先是对s1初始化的,后来对s2进行复制构造,但是Stack并没有显式复制构造,那么编译器就生成一个复制构造,但是对Stack里面的都是直接的值拷贝,就连指针所指向的空间都是一样的,那么当最后创建的s2先析构的时候那块空间已经没了,但是s1那就是野指针了,再去析构就会报错。

所以这是浅拷贝,也叫值拷贝。

如果要避免以上的问题,就要进行深拷贝了,也就是把s2的指针开辟同样大的空间,地址和s1的指针不一样。
在这里插入图片描述
注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请时,则拷贝构造函数是一定要写的,否则就是浅拷贝。
需要去写析构函数的类,就要去写深拷贝的拷贝构造。
不需要写析构函数的类,默认生成的浅拷贝就可以用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值