c++深拷贝 浅拷贝 重载赋值运算

拷贝构造

何时使用

用一个最简单的例子来说明:

class People{
private:
    int age;
    char *name;
};

使用情况1: 对象作为值传递作为函数传入参数, 如:

bool is_adult(People zy){
	return zy.get_age()>=18;
}

但当对象的引用作为函数传入参数,如:

bool is_adult(People &zy){
	return zy.get_age()>=18;
}

就不用调用拷贝构造,这是很简单的逻辑,引用变量是对象的一个别名,也就是说,它是某个已存在变量的另一个名字,此时不必重新再创建一个对象。

使用情况2: 对象作为值传递作为函数返回值,如:

People older(People zy,People cmh){
	if(zy.get_age()>cmh.get_age())
		return zy;
	return cmh;
}

此时返回cmh时作为对象值返回而不是引用返回,需要重新创建一个对象。

使用情况3: 在用一个已存在的对象来初始化一个未创建的对象时:

People cmh(zy);
People cmh=zy;

不管是用 = = =或者用 ( ) () ()此时均是调用拷贝构造函数而不是 = = =赋值重载符,因为此时 c m h cmh cmh对象未创建。因此最好用第一种括号写法而不是第二种等于号写法,避免混淆。

使用方法

参数: const & 对象
const 是因为要求传进来的对象不可改变。
使用&是因为当我们使用值传递的时候,深拷贝的第一种使用情况:“对象作为值传递作为函数参数”,拷贝构造函数也是一个函数,若传入参数是值传递而不是引用传递,则会再次调用一个拷贝构造函数,新的拷贝构造函数会调用一个新的拷贝构造函数…无限调用就陷入死循环了。

返回: 无返回值,此时为构造函数,构造函数不需要返回值。

简单模板:

People(const People &p){//const 引用 类型 
	//对非动态开辟的成员进行赋值
	age=p.age;
	//对指针类型的成员开辟空间再赋值
	name=new char[strlen(p.name)];
	strncpy(name,p.name,strlen(p.name));
}

深拷贝与浅拷贝

如果在类内无指针类型的成员,则深拷贝和浅拷贝没有区别直接进行值拷贝即可:

struct Patient{
	int age;
	int id;
	char gender;
}

但是若像 P e o p l e People People有名字这个字符指针的类,深拷贝和浅拷贝就有区别。
若我们自己不写一个深拷贝函数,则程序会自动执行浅拷贝构造函数,如在以上定义的 P e o p l e People People类中,程序默认的浅拷贝构造函数为:

People(const People &p){
	age=p.age;
	name=p.name;
}

若采用浅拷贝构造,当主函数中内容为

People cmh(zy);

内存中会发生如下情况,cmh的name指针和zy的name指针均指向同一个地址。这样会发生的结果是:当zy析构时会将释放name指向的内存,相当于 0 x 0000 0x0000 0x0000地址存放的内容被销毁,此时zy.name仍然指向 0 x 0000 0x0000 0x0000,只是此处没有内容了。接下来当cmh析构时会尝试再次cmh.name释放,但是此时cmh.name指向的地址已经没有内容可供销毁,因此会发生报错。
总之动态开辟和销毁是配对的,new一次就需要delete一次, 浅拷贝会造成new一次而delete两次的错误,因此我们需要自己重写深拷贝,让cmh.name指向别的空间,而不指向zy.name指向的空间。
在这里插入图片描述

赋值重载

何时使用

对象已经存在,如下 c a s e 1 case 1 case1 = = =即调用了赋值重载函数。
而当对象在创建时,如下 c a s e 2 case2 case2即使用了 = = =,也不会调用赋值重载函数,而是调用拷贝构造函数。

//case 1:
People cmh;
cmh=zy;
//case 2:
People cmh(zy);

使用方法

参数: const & 对象。
返回值: 对象引用
重载赋值函数的返回值和传入值都需要使用对象引用,因为它也是一个函数,若采用值传递会在赋值函数中再调用一次拷贝构造函数,浪费时间和空间。
简单模板:

People & operator=(const People&  p){
   	age=p.age;
   	name=new char[strlen(p.name)];
   	strncpy(name,p.name,strlen(p.name));
   	return *this;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值