拷贝构造函数与深浅拷贝以及赋值表达式的关系

本文详细解析了C++中拷贝构造函数的作用及其实现方式,包括浅拷贝和深拷贝的区别,以及如何避免浅拷贝带来的问题。通过实例展示了拷贝构造函数在对象初始化和赋值运算中的应用。

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

在C++中,下面三种对象需要拷贝的情况。因此,拷贝构造函数将会被调用。
1). 一个对象以值传递的方式传入函数体
2). 一个对象以值传递的方式从函数返回
3). 一个对象需要通过另外一个对象进行初始化搜索

拷贝构造函数赋值运算的行为相似,用一个已存在的对象去构造一个不存在的对象(构造之前不存在),就是拷贝构造。用一个已存在的对象去覆盖另一个已存在的对象,就是赋值运算,见如下例子。

using namespace std;
class CStudent
{
public:
	CStudent(char* name);
	~CStudent();
	CStudent(const CStudent& p);
	void print();
	char* _name;

	CStudent& operator=(const CStudent& rhs)
	{
		cout <<"赋值运算"<< endl;
		if (this == &rhs) {
			return *this;
		}
		this->_name = rhs._name;
		return *this;
	}

private:

};

CStudent::CStudent(const CStudent& p)
{
	cout << "拷贝构造函数" << endl;
	_name = new char[strlen(p._name) + 1]; //深拷贝
	if (_name != NULL)
		strcpy_s(_name, strlen(p._name) + 1, p._name);
}

CStudent::CStudent(char* name)
{
	cout << "构造函数" << endl;
	_name = new char[strlen(name) + 1];
	if (_name != NULL)
	{
		strcpy_s(_name, strlen(name)+1,name);
	}
}

CStudent::~CStudent()
{
	delete _name;
}

void CStudent::print()
{
	cout<<_name<<endl;
}
void main()
{
	CStudent stu1("tom");//调用构造函数
	CStudent stu2 =stu1;//调用拷贝构造函数
	CStudent stu3("jack");//调用构造函数
	stu1 = stu3;//调用赋值运算
	cin.get();
}

运行结果:
在这里插入图片描述

如果我们没有写拷贝构造函数,那么编译器会调用默认的拷贝构造函数进行浅拷贝。
浅拷贝的意思就是内存中只有一份"tom",对象stu1的name指针指向了它.把stu1拷贝给stu2后,stu2的name指向也指向了"tom",指向的是内存中同一块地址.这就会出现一个问题:当stu1的对象被销毁了,那么stu1的name指向的"tom"也会被销毁,由于stu2中的name也是指向"tom"的,所以这时stu2中的name就变成空的了,甚至是乱码。
如下例子:

class CStudent
{
public:
	CStudent(char* name);
	~CStudent();
	void print();
	char* _name;
private:

};

CStudent::CStudent(char* name)
{
	_name = new char[strlen(name) + 1];
	if (_name != NULL)
	{
		strcpy_s(_name, strlen(name)+1,name);
	}
}

CStudent::~CStudent()
{
	delete _name;
}

void CStudent::print()
{
	cout<<_name<<endl;
}
void main()
{
	CStudent stu1("tom");
	CStudent stu2 =stu1;
	cout << stu1._name << endl;
	delete stu1._name;
	cout << stu2._name << endl;
	cin.get();
}

运行结果:
在这里插入图片描述
深拷贝是既拷贝成员,又拷贝资源的方式。深拷贝是指源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外一个对象造成影响。举个例子,一个人名叫张三,后来用他克隆(假设法律允许)了另外一个人,叫李四,不管是张三缺胳膊少腿还是李四缺胳膊少腿都不会影响另外一个人。比较典型的就是Value(值)对象,如预定义类型Int32,Double,以及结构(struct),枚举(Enum)等。
系统提供的默认拷贝构造函数为浅拷贝,深拷贝必须自己定义。修改拷贝构造函数,将上面的例子修改为下面的例子:

class CStudent
{
public:
	CStudent(char* name);
	~CStudent();
	CStudent(const CStudent& p);
	void print();
	char* _name;

private:

};
CStudent::CStudent(const CStudent& p)//拷贝构造函数
{
	_name = new char[strlen(p._name) + 1]; //深拷贝
	if (_name != NULL)
		strcpy_s(_name, strlen(p._name) + 1, p._name);
}

CStudent::CStudent(char* name)
{
	_name = new char[strlen(name) + 1];
	if (_name != NULL)
	{
		strcpy_s(_name, strlen(name)+1,name);
	}
}

CStudent::~CStudent()
{
	delete _name;
}

void CStudent::print()
{
	cout<<_name<<endl;
}
void main()
{
	CStudent stu1("tom");
	CStudent stu2 =stu1;
	cout << stu1._name << endl;
	delete stu1._name;
	cout << stu2._name << endl;
	cin.get();
}

运行结果:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值