拷贝构造函数和赋值运算符区别

2023-10-30

‘=’只有在赋值时,才调用赋值函数,当在声明变量时,B b3=b1和B b4(b3)调用的函数是一样的,均为拷贝构造函数。

一、
拷贝构造,是一个的对象来初始化一边内存区域,这边内存区域就是你的新对象的内存区域赋值运算,对于一个已经被初始化的对象来进行operator=操作
class A;
A a;
A b=a; //拷贝构造函数调用
//或
A b(a); //拷贝构造函数调用
///
A a;
A b;
b =a; //赋值运算符调用
你只需要记住,在C++语言里,
String s2(s1);
String s3 = s1;
只是语法形式的不同,意义是一样的,都是定义加初始化,都调用拷贝构造函数。

二、
一般来说是在数据成员包含指针对象的时候,应付两种不同的处理需求的 :
一种是复制指针对象,
一种是引用指针对象 copy大多数情况下是复制,=则是引用对象的
即 深拷贝 和 浅拷贝
拷贝构造函数 是深拷贝
例子:
class A
{
int nLen;
char * pData;
}
显然
A a, b;
a=b的时候,对于pData数据存在两种需求
第一种copy
a.pData = new char [nLen];
memcpy(a.pData, b.pData, nLen);
另外一种(引用方式):
a.pData = b.pData

通过对比就可以看到,他们是不同的
往往把第一种用copy使用,第二种用=实现

三、
和拷贝构造函数的实现不一样
拷贝构造函数首先是一个构造函数,它调用的时候产生一个对象,是通过参数传进来的那个对象来初始化,产生的对象。
operator=();是把一个对象赋值给一个原有的对象,所以如果原来的对象中有内存分配要先把内存释放掉,而且还要检查一下两个对象是不是同一个对象,如果是的话就不做任何操作。

一个例程
(自:http://www.vckbase.com
以下讨论中将用到的例子:
class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //类的对象中包含指针,指向动态分配的内存资源
int nSize;
};
这个类的主要特点是包含指向其他资源的指针。pBuffer指向堆中分配的一段内存空间。

一、拷贝构造函数
int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init(40);

//现在需要另一个对象,需要将他初始化称对象一的状态
CExample theObjtwo=theObjone;
...

}
语句”CExample theObjtwo=theObjone;” 是 浅拷贝
如果类中定义了拷贝构造函数,这对象建立时,调用的将是拷贝构造函数,在拷贝构造函数中,可以根据传入的变量,复制指针所指向的资源。
拷贝构造函数的格式为:构造函数名(对象的引用)
提供了拷贝构造函数后的CExample类定义为:
class CExample
{
public:
CExample(){pBuffer=NULL; nSize=0;}
~CExample(){delete pBuffer;}
CExample(const CExample&); //拷贝构造函数
void Init(int n){ pBuffer=new char[n]; nSize=n;}
private:
char *pBuffer; //类的对象中包含指针,指向动态分配的内存资源
int nSize;
};
CExample::CExample(const CExample& RightSides) //拷贝构造函数的定义
{
nSize=RightSides.nSize; //复制常规成员
pBuffer=new char[nSize]; //复制指针指向的内容
memcpy(pBuffer,RightSides.pBuffer,nSize*sizeof(char));
}

1 定义新对象,并用已有对象初始化新对象时,CExample(const CExample& RightSides)将被调用,而已有对象用别名RightSides传给构造函数,以用来作复制。
原则上,应该为所有包含动态分配成员的类都提供拷贝构造函数。

2 当对象直接作为参数传给函数时,函数将建立对象的临时拷贝,这个拷贝过程也将调同拷贝构造函数。
例如
BOOL testfunc(CExample obj);
testfunc(theObjone); //对象直接作为参数。
BOOL testfunc(CExample obj)
{
//针对obj的操作实际上是针对复制后的临时拷贝进行的
}

3 还有一种情况,也是与临时对象有关的
当函数中的局部对象被被返回给函数调者时,也将建立此局部对象的一个临时拷贝,拷贝构造函数也将被调用
CTest func()
{
CTest theTest;
return theTest
}
二、赋值符的重载
下面的代码与上例相似
int main(int argc, char* argv[])
{
CExample theObjone;
theObjone.Init(40);

CExample theObjthree;
theObjthree.Init(60);
//现在需要一个对象赋值操作,被赋值对象的原内容被清除,并用右边对象的内容填充。
theObjthree=theObjone;
return 0;

}

也用到了”=”号,但与”一、”中的例子并不同,”一、”的例子中,”=”在对象声明语句中,表示初始化。更多时候,这种初始化也可用括号表示。
例如 CExample theObjone(theObjtwo);
而本例子中,”=”表示赋值操作。将对象theObjone的内容复制到对象theObjthree;,这其中涉及到对象theObjthree原有内容的丢弃,新内容的复制。
但”=”的缺省操作只是将成员变量的值相应复制。旧的值被自然丢弃。
由于对象内包含指针,将造成不良后果:指针的值被丢弃了,但指针指向的内容并未释放。指针的值被复制了,但指针所指内容并未复制。
因此,包含动态分配成员的类除提供拷贝构造函数外,还应该考虑重载”=”赋值操作符号。
类定义变为:
class CExample
{

CExample(const CExample&); //拷贝构造函数
CExample& operator = (const CExample&); //赋值符重载

};

//赋值操作符重载
CExample & CExample::operator = (const CExample& RightSides)
{
nSize=RightSides.nSize; //复制常规成员
char *temp=new char[nSize]; //复制指针指向的内容
memcpy(temp,RightSides.pBuffer,nSize*sizeof(char));
delete []pBuffer; //删除原指针指向内容 (将删除操作放在后面,避免X=X特殊情况下,内容的丢失)
pBuffer=temp; //建立新指向
return *this
}
三、拷贝构造函数使用赋值运算符重载的代码。
CExample::CExample(const CExample& RightSides)
{
pBuffer=NULL;
*this=RightSides //调用重载后的”=”
}
本文转自CSDN博客

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

拷贝构造函数和赋值运算符区别 的相关文章

随机推荐

  • 常用思维模型

    产品经理必知的几个思维模型 1 PEST分析 2 SWOT分析 3 PMF模型 4 MVP模型 5 AARRR模型 6 SMART模型 7 WHY分析法 8 Y模型分析法 9 KANO模型 10 四象限法则 11 MECE原则 12 RFM
  • GCP Monitoring and Dashboarding Multiple Projects from a Single Workspace Lab

    最后更新2022 03 17 这个室验是一个dashboard看多个projects的信息 照例先进console 不同的是同时给了3个projects 记录好哪个用于monitor 哪个是worker1和worker2 具体没区别 但以后
  • 【zookeeper】zookeeper 启动 源码解读

    文章目录 1 概述 2 QuorumPeerMain 3 单机模式 4 集群模式 4 1 createFactory 4 2 getQuorumPeer 4 3 LearnerType 4 4 start 4 4 1 loadDataBas
  • OpenWrt设置.端口转发和远程访问路由器

    到Luci界面 网络 gt 防火墙 首先 先来说下如何设置端口转发 点击上方的 端口转发 新建端口转发 处填写名称 随便 外网端口 内部IP地址 内网端口 图中的设置表示将外网82端口上的TCP数据转发到内网192 168 1 11的80端
  • 【Lua学习】Lesson5.程序的时序、线程及任务同步

    基本时序 先把分析一下上一笔记中的代码 function LedRunning do something sys timerStart LedRunning 200 200ms定时执行此函数 end LedRunning 首先是定义了一个功
  • 各大工作室都在用的视觉特效软件,开启你的虚拟制作之旅

    为您的虚拟制作设置的免费视觉特效工具 使用领先工作室们所信任的创意资源管理软件 免费开始您的下一个虚拟制作项目 花更多时间在创作上 更少时间在设置上 增强型Studio包 现已可以部署在微软 Azure 上使用 包含了您所需要的所有工具 包
  • 超详细教程-Linux服务器安装jenkins

    2 一 步骤目录 1 安装JDK 2 安装Jenkins 3 修改Jenkins配置 4 启动Jenkins 5 服务器开放端口 打开浏览器 6 获取管理员密码 7 自定义Jenkins 8 创建第一个管理员用户 二 具体操作 1 安装JD
  • Postman如何进行参数化

    前言 Postman作为一款接口测试工具 受到了非常多的开发工程师的拥护 那么做为测试 了解Postman这款工具就成了必要的了 这篇文章就是为了解决Postman怎么进行参数化的 全局变量 全局变量是将这个变量设置成整个程序的都可以用 不
  • 暴力枚举、全排列

    1 带分数 题目分析 假设待求的数 num a b c 对于样例1 100 3 69258 714 a 3 b 69258 c 714 我们首先对 123456789 进行全排列 然后对于其中的每个全排列进行分段 比如样例中涉及的排列之一
  • 哔哩哔哩能下游戏?B站游戏下载

    哔哩哔哩不仅可以看视频和社区活动 还可以下载游戏 你知道吗 哔哩哔哩要如何下载游戏呢 本期教程就来教教大家B站游戏下载的方法 哔哩哔哩下载游戏方法教程 1 打开b站之后 点击游戏中心图标 2 进去哔哩哔哩游戏中心之后 点击底部我的 3 在我
  • 使用UmiJS开发项目(上)

    目录 一 Umi是什么 二 项目初始化 三 配置prettier eslint stylelint 四 配置文件 五 多环境多配置文件 前段时间公司重构的项目中选用Umi框架 使用的过程中整理并封装了一些Umi常用的功能 由于文章篇幅较长
  • 解压文件win10自动删除

    解压文件 包含一个破解软件 被win10自动删除 复制也会提示 无法完成操作 因为文件包含病毒或潜在的垃圾软件 解决办法 找到病毒和威胁防护 找到被隔离的威胁 操作允许在设备上即可
  • Java 11 升Java 17 重要特性必读(摘录)

    1 JDK 17 在 2021 年 9 月 14 号正式发布了 根据发布的规划 这次发布的 JDK 17 是一个长期维护的版本 LTS SpingFramework 6 和SpringBoot 3中默认将使用JDK 17 所以JDK 17必
  • vue封装组件之上传图片组件(el-upload)

    vue封装组件之上传图片组件 el upload 未上传状态 上传状态 其他状态 查看 删除 自定义组件文件名称 这里叫UploadImg vue
  • 子串判断

    链接 https www nowcoder com questionTerminal 917a800d4de1423394827932f4725c68 orderByHotValue 1 done 0 pos 10 onlyReferenc
  • 亲身经历提醒大家,工作千万不要太快做完,快了领导就会认为你很能干,把最急、最难的任务分给你!...

    职场上 如何合理把握工作节奏 一位网友用亲身经历提醒大家 上班的时候千万不要搞太快了 搞快了领导就会认为你很能干 分任务的时候 永远把最多 最急 最难 最复杂的业务都交给你 然后别人搞完都下班了 唯独你一个人坐那加班 真是讽刺 许多网友都有
  • JavaScript中的类型详解

    一 JavaScript中的类型 JavaScript中的类型可以分为基本数据类型和引用类型两种 基本类型值 指的是保存在栈内存中的简单数据段 引用类型值 指的是那些保存在堆内存中的对象 意思是 栈内存中保存的实际上只是一个指针 这个指针指
  • 五位杰出的中国女科学家--巾帼不让须眉,见证科技中的“她力量”

    今年一月 英国广播公司 BBC 公布 20世纪最具标志性人物 票选活动 中国首位诺贝尔生理学或医学奖得主屠呦呦与居里夫人 爱因斯坦等一同入围 BBC还专门制作了介绍短片 讲述屠呦呦发现青蒿素的传奇故事 去年也是科研女性表现亮眼的一年 中国科
  • FBX动画导入Unity

    Unity动画 1 1 第一章 Unity导入FBX模型动画但不能动 文章目录 Unity动画 前言 一 FBX模型动画 二 Unity导入后设置参数 1 设置材质 2 设置动画 总结 前言 随着AR VR等技术发展 摸一手Unity动画总
  • 拷贝构造函数和赋值运算符区别

    只有在赋值时 才调用赋值函数 当在声明变量时 B b3 b1和B b4 b3 调用的函数是一样的 均为拷贝构造函数 一 拷贝构造 是一个的对象来初始化一边内存区域 这边内存区域就是你的新对象的内存区域赋值运算 对于一个已经被初始化的对象来进