C++深浅拷贝

关于深浅拷贝和值语义/引用语义的学习和理解


最近在复习C++基础,看了一些关于深拷贝和浅拷贝的知识贴,发现以前对这个问题的理解比较浅,下面记录一下理解过程。

首先看下值语义(value semantics)和引用语义(reference semantics)的概念(部分转载自:https://www.jianshu.com/p/590b618f3618)

值语义:对象的拷贝与原对象无关,c++中将基础类型都定义为值语义,c++规定凡是能够放入标准容器内的类型必须具有值语义。
对于值语义的对象,在x = y完成复制后,y的状态改变不再影响到x,这个特性称之为独立性(independence)。复制的过程可认为是深拷贝,即完全复制一个独立于原来对象的对象。C++提供的模板类大部分都是值语义的,如 std::basic_string、std::vector 等。

引用语义:一个对象被系统标准的复制函数复制后,与被复制的对象共享底层资源,只要一个改变了另外一个就会改变。

c++编译器会为类提供默认的拷贝构造函数和重载函数,一般我们不需要自己重写这些,因为只要每个数据成员都为值语义,编译器就可以调用默认的成员拷贝。
比如下面的类

// An highlighted block
class X
{
  int x;
  int y;
};
X a;
X b = a;

a 和 b是两个独立的对象,没有问题。

下面我们向类X中加入一个指针(或者引用),事情就不一样了

// An highlighted block
class X
{
  int x;
  int y;
  char* p;
};
X a;
X b = a;

这时候,a.p 和b.p 指向的是同一片内存区。那么如果原来的物体销毁了,但是现在拷贝的物体还在,那么这时候你拷贝后的物体的成员指针就是一个悬挂指针,指向了不再存在的物体,那么你访问的话,那就不知道会发生什么了。。

这种情况下,需要我们自己定义拷贝构造函数以及析构函数,如

// An highlighted block
class X
{
  X(const X& oldX)//拷贝构造函数
  {
  		p = new char[strlen(oldX.p)+1];//重新开辟内存空间
  		strcpy_s(p,strlen(oldX.p)+1,oldX.p);
  		x = oldX.x;
  		y = oldX.y;
  }
  ~X()//析构函数
  {
  		delete p;
  		p = nullptr;
  }
  int x;
  int y;
  char* p;
};
X a;
X b = a;

这样就没问题了。

总结

浅拷贝:将源对象的值拷贝到目标对象中去,对指针来说,本质上来说源对象和目标对象共用一份实体,只是所引用的变量名不同,地址其实还是相同的。

深拷贝,拷贝的时候先开辟出和源对象大小一样的空间,然后将源对象里的内容拷贝到目标对象中去,这样两个指针就指向了不同的内存位置。并且里面的内容是一样的,这样不但达到了我们想要的目的,还不会出现问题,两个指针先后去调用析构函数,分别释放自己所指向的位置。即为每次增加一个指针,便申请一块新的内存,并让这个指针指向新的内存,深拷贝情况下,不会出现重复释放同一块内存的错误。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值