C++深拷贝实现代码举例

拷贝构造函数:用一个已有的对象来初始化一个被创建的同类的对象,是一种特殊的构造函数。

浅拷贝和深拷贝的区别是什么呢?
下面是一个Test类,类中包含一个私有的指针p, 现在我想创建两个对象,其中一个对象通过复制另一个对象创建,于是编写了这样的代码:

class Test{
	private:
		char *p;
	public:
		Test(const char *str){	
		p=new char[strlen(str)+1];
		strcpy(p,str);
		printf("Test cntr.%s\n",p);
		}
	
		~Test(){
		printf("~Test cntr.%s\n",p);
		delete []p;
		p=NULL;
		}		
};

int main(){
	 Test t1("hello");
	 Test t2(t1);
}

运行结果是这样的:
在这里插入图片描述
很明显,创建失败了。。。从结果上可以看到程序只调用了一次程序中带参数的构造函数,却析构了两次,而且第一个对象的析构结果啥玩意儿?(先构造后析构的原则)原来如果我们没有主动编写类的拷贝构造函数,系统就会自动生成一个缺省拷贝构造函数。而缺省拷贝构造函数在拷贝过程中是位复制,把一个对象按位复制过来,对于指针型的成员变量只复制指针本身,而不复制指针所指向的内容。
在这里插入图片描述
t1.p 和 t2.p指向的是同一块地址,所以构造函数只调用了一次,析构时先释放了 t2.p 指向的内存,再析构 t1.p 时则要访问同一个已经被释放了的内存单元,这时则出现了内存管理错误!

那怎么样既复制指针本身,也复制指针内容呢?不要缺省拷贝构造函数,我们再编写个能实现深拷贝的构造函数,为t2新开辟一个内存单元
在这里插入图片描述
我加了个拷贝构造函数

		Test(const Test &t)
		{
		p=new char[strlen(t.p+1)];
		strcpy(p,t.p);
		printf("Test copy.%s\n",p);		
		}

运行结果:
在这里插入图片描述
复制成功*.*

解释一下 Test(const Test &t) 这里为什么是引用。 如果是Test(const Test t) ,这时实参到形参的传递是值传递,也就是实参复制一份给形参。可是在执行Test t2(t1)调用这个拷贝构造函数时,还没有复制t1, 为了避免出现 未复制–>已复制–>再复制 的乌龙情况,则需要引用。

除了使用重载拷贝构造函数的方法,还可以通过重载赋值运算符的方法(赋值函数)实现深拷贝。不过要注意拷贝构造函数与赋值函数的区别:

class Test{
	private:
		char *p;
	public:
		Test(const char *str){	
		p=new char[strlen(str)+1];
		strcpy(p,str);
		printf("Test cntr.%s\n",p);
		}
		
		Test(const Test &t)
		{
		p=new char[strlen(t.p+1)];
		strcpy(p,t.p);
		printf("Test copy.%s\n",p);		
		}                
		
		Test &operator=(const Test &t){
			if(this!=&t){
				delete [] p;//赋值函数中要先删除对象自己本身的指针空间 		
				p=new char[strlen(t.p+1)];
				strcpy(p,t.p);
			}
		printf("Test == opertor.%s\n",p);	
		return *this;	
		}
		
		~Test(){
		printf("~Test cntr.%s\n",p);
		delete []p;
		p=NULL;
		}		
};

int main(){
	 Test t1("hello");
	 Test t2(t1);
	 Test t3="world";
	 Test t4(t3);
	 t4=t1;//赋值函数
}

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

t4=t1调用的是赋值函数,注意到区别了吗?
在创建对象的时候调用拷贝构造函数,对象已存在再复制时调用的是赋值函数。 Test t1(“hello”); Test t2=t1; 这样也是调用拷贝构造函数,但为了形式上区分赋值函数,将Test t2=t1;写成Test t2(t1);
其次赋值的本质是删除原值,赋予新值,所以赋值函数中要先删除对象自己本身的指针空间。

重点
浅拷贝:
缺省拷贝构造函数在拷贝过程中是位复制,把一个对象按位复制过来,对于指针型的成员变量只复制指针本身,而不复制指针所指向的内容。

深拷贝:由于对象的复制默认都是浅拷贝,如果我们想要的不仅复制指针本身,也要复制指针内容,则需要重载拷贝构造函数或者编写赋值函数(注意两者区别),使之成为深拷贝。

最近在整理一些知识点,如有错误之处,希望大家多多指正呀!

  • 17
    点赞
  • 36
    收藏
    觉得还不错? 一键收藏
  • 9
    评论
评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值