C++类对象的深拷贝、浅拷贝构造函数

海康视觉平台VisionMaster使用学习笔记(1) 双击图像源设置图像源的属性,像素格式分为Mono8和RDB24分别对应导入的图像是彩色还是黑白。打开相机驱动软件MVS,对连接的相机进行属性上的配置,先对相机的IP进行对应的设置。将自动触发的使能打开,保存配置好的相机属性,默认保存到用户集1中。点击MVS软件中的触发按钮,查看相机是否进行正常的触发拍照。打开VM软件添加一个图像源,选择图像源选项拖出图像源。回到VM软件中将选择相机选项选择到配置好参数的相机。取图方式也可以调整为相机取图,将图像源改为相机。双击相机进行连接后对相机的属性进行配置。 阅读详情

在学习这一章内容前我们已经学习过了类的构造函数和析构函数的相关知识,对于普通类型的对象来说,他们之间的复制是很简单的,例如:

int a = 10;
int b =a;


  自己定义的类的对象同样是对象,谁也不能阻止我们用以下的方式进行复制,例如:

 

 #include <iostream>
usingnamespacestd;

classTest
{
public:
Test(inttemp)
{
p1=temp;
}
protected:
intp1;

};

voidmain()
{
Test a(99);
Test b=a;
}


   普通对象和类对象同为对象,他们之间的特性有相似之处也有不同之处,类对象内部存在成员变量,而普通对象是没有的,当同样的复制方法发生在不同的对象上 的时候,那么系统对他们进行的操作也是不一样的,就类对象而言,相同类型的类对象是通过拷贝构造函数来完成整个复制过程的,在上面的代码中,我们并没有看 到拷贝构造函数,同样完成了复制工作,这又是为什么呢?因为当一个类没有自定义的拷贝构造函数的时候系统会自动提供一个默认的拷贝构造函数,来完成复制工 作。
 
  下面,我们为了说明情况,就普通情况而言(以上面的代码为例),我们来自己定义一个与系统默认拷贝构造函数一样的拷贝构造函数,看看它的内部是如何工作的!
 
  代码如下:

 

 #include <iostream>
usingnamespacestd;

classTest
{
public:
Test(inttemp)
{
p1=temp;
}
Test(Test &c_t)//这里就是自定义的拷贝构造函数
{
cout<<"进入copy构造函数"<p1=c_t.p1;//这句如果去掉就不能完成复制工作了,此句复制过程的核心语句
}
public:
intp1;
};

voidmain()
{
Test a(99);
Test b=a;
cout<cin.get();
}


  上面代码中的Test(Test &c_t)就是我们自定义的拷贝构造函数,拷贝构造函数的名称必须与类名称一致,函数的形式参数是本类型的一个引用变量,且必须是引用。
 
   当用一个已经初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用,如果你没有自定义拷贝构造函数的时候系统将 会提供给一个默认的拷贝构造函数来完成这个过程,上面代码的复制核心语句就是通过Test(Test &c_t)拷贝构造函数内的p1=c_t.p1;语句完成的。如果取掉这句代码,那么b对象的p1属性将得到一个未知的随机值;
 
  下面我们来讨论一下关于浅拷贝和深拷贝的问题。
 
   就上面的代码情况而言,很多人会问到,既然系统会自动提供一个默认的拷贝构造函数来处理复制,那么我们没有意义要去自定义拷贝构造函数呀,对,就普通情 况而言这的确是没有必要的,但在某写状况下,类体内的成员是需要开辟动态开辟堆内存的,如果我们不自定义拷贝构造函数而让系统自己处理,那么就会导致堆内 存的所属权产生混乱,试想一下,已经开辟的一端堆地址原来是属于对象a的,由于复制过程发生,b对象取得是a已经开辟的堆地址,一旦程序产生析构,释放堆 的时候,计算机是不可能清楚这段地址是真正属于谁的,当连续发生两次析构的时候就出现了运行错误。

 

为了更详细的说明问题,请看如下的代码。

 

 #include <iostream>
usingnamespacestd;

classInternet
{
public:
Internet(char*name,char*address)
{
cout<<"载入构造函数"<strcpy(Internet::name,name);
strcpy(Internet::address,address);
cname=newchar[strlen(name)+1];
if(cname!=NULL)
{
strcpy(Internet::cname,name);
}
}
Internet(Internet &temp)
{
cout<<"载入COPY构造函数"<strcpy(Internet::name,temp.name);
strcpy(Internet::address,temp.address);
cname=newchar[strlen(name)+1];//这里注意,深拷贝的体现!
if(cname!=NULL)
{
strcpy(Internet::cname,name);
}
}
~Internet()
{
cout<<"载入析构函数!";
delete[] cname;
cin.get();
}
voidshow();
protected:
charname[20];
charaddress[30];
char*cname;
};
voidInternet::show()
{
cout<}
voidtest(Internet ts)
{
cout<<"载入test函数"<}
voidmain()
{
Internet a("中国软件开发实验室","www.cndev-lab.com");
Internet b =a;
b.show();
test(b);
}

 

  上面代码就演示了深拷贝的问题,对对象b的cname属性采取了新开辟内存的方式避免了内存归属不清所导致析构释放空间时候的错误,最后我必须提一下,对于上面的程序我的解释并不多,就是希望读者本身运行程序观察变化,进而深刻理解。
 
  深拷贝和浅拷贝的定义可以简单理解成:如果一个类拥有资源(堆,或者是其它系统资源),当这个类的对象发生复制过程的时候,这个过程就可以叫做深拷贝,反之对象存在资源但复制过程并未复制资源的情况视为浅拷贝。
 
  浅拷贝资源后在释放资源的时候会产生资源归属不清的情况导致程序运行出错,这点尤其需要注意!

 

 

  以前我们的教程中讨论过函数返回对象产生临时变量的问题,接下来我们来看一下在函数中返回自定义类型对象是否也遵循此规则产生临时对象!
 
  先运行下列代码: 

 

 #include <iostream>
usingnamespacestd;

classInternet
{
public:
Internet()
{

};
Internet(char*name,char*address)
{
cout<<"载入构造函数"<strcpy(Internet::name,name);
strcpy(Internet::address,address);
}
Internet(Internet &temp)
{
cout<<"载入COPY构造函数"<strcpy(Internet::name,temp.name);
strcpy(Internet::address,temp.address);
cin.get();
}
~Internet()
{
cout<<"载入析构函数!";
cin.get();
}
protected:
charname[20];
charaddress[20];
};
Internet tp()
{
Internet b("中国软件开发实验室","www.cndev-lab.com");
returnb;
}
voidmain()
{
Internet a;
a=tp();
}


  从上面的代码运行结果可以看出,程序一共载入过析构函数三次,证明了由函数返回自定义类型对象同样会产生临时变量,事实上对象a得到的就是这个临时Internet类类型对象temp的值。
 
  这一下节的内容我们来说一下无名对象。
 
  利用无名对象初始化对象系统不会不调用拷贝构造函数。
 
  那么什么又是无名对象呢?
 
  很简单,如果在上面程序的main函数中有:

 

 Internet ("中国软件开发实验室","www.cndev-lab.com ");


    这样的一句语句就会产生一个无名对象,无名对象会调用构造函数但利用无名对象初始化对象系统不会不调用拷贝构造函数!

 

 

  下面三段代码是很见到的三种利用无名对象初始化对象的例子。

 

 #include <iostream>
usingnamespacestd;

classInternet
{
public:
Internet(char*name,char*address)
{
cout<<"载入构造函数"<strcpy(Internet::name,name);
}
Internet(Internet &temp)
{
cout<<"载入COPY构造函数"<strcpy(Internet::name,temp.name);
cin.get();
}
~Internet()
{
cout<<"载入析构函数!";
cin.get();
}
public:
charname[20];
charaddress[20];
};

voidmain()
{
Internet a=Internet("中国软件开发实验室","www.cndev-lab.com");
cout<cin.get();
}


  上面代码的运行结果有点“出人意料”,从思维逻辑上说,当无名对象创建了后,是应该调用自定义拷贝构造函数,或者是默认拷贝构造函数来完成复制过程的,但事实上系统并没有这么做,因为无名对象使用过后在整个程序中就失去了作用,对于这种情况c++会把代码看成是:
 
  Internet a("中国软件开发实验室","www.cndev-lab.com ");
 
  省略了创建无名对象这一过程,所以说不会调用拷贝构造函数。
 
  最后让我们来看看引用无名对象的情况。

 

 #include <iostream>
usingnamespacestd;

classInternet
{
public:
Internet(char*name,char*address)
{
cout<<"载入构造函数"<strcpy(Internet::name,name);
}
Internet(Internet &temp)
{
cout<<"载入COPY构造函数"<strcpy(Internet::name,temp.name);
cin.get();
}
~Internet()
{
cout<<"载入析构函数!";
}
public:
charname[20];
charaddress[20];
};

voidmain()
{
Internet &a=Internet("中国软件开发实验室","www.cndev-lab.com");
cout<cin.get();
}


  引用本身是对象的别名,和复制并没有关系,所以不会调用拷贝构造函数,但要注意的是,在c++看来:

 

 Internet &a=Internet("中国软件开发实验室",www.cndev-lab.com );


  是等价与:

 

 Internet a("中国软件开发实验室",www.cndev-lab.com );


  的,注意观察调用析构函数的位置(这种情况是在main()外调用,而无名对象本身是在main()内析构的)。

 

 

手把手教你用TBtools+MCScanX完成玉米基因家族共线性分析(附完整代码) 本文提供了一套完整的玉米基因家族共线性分析实战流程,详细讲解了如何从数据准备、格式处理开始,利用DIAMOND进行快速比对,再结合MCScanX进行核心共线性区块鉴定,最后通过TBtools实现从全基因组圈图到特定基因家族微共线性图的可视化。教程包含可直接运行的代码与常见问题解决方案,帮助研究者高效完成从命令行计算到图形化展示的全过程。 阅读详情

相关推荐

华硕ROG玩家国度安装Ubuntu双系统避坑指南:安全启动密钥那些事儿

本文详细解析了在华硕ROG玩家国度设备上安装Ubuntu双系统时,如何正确处理BIOS中的安全启动(Secure Boot)与密钥管理,避免常见的引导失败和Windows系统无法启动问题。指南提供了从数据备份、启动盘制作到BIOS精细设置(如将OS Type改为Other OS而非简单关闭Secure Boot)以及分区规划的完整流程,确保两个系统都能稳定共存。

weixin_29219189的博客 754

C++:深拷贝和浅拷贝

对于基本类型的数据以及简单的对象,它们之间的拷贝非常简单,就是按位复制内存。

crossoverpptx的博客 2262

文献阅读笔记:量子微波测量技术综述

量子微波测量技术研究进展:量子微波测量技术利用里德堡原子与微波电场的相干相互作用,突破了传统测量方法的物理限制。该技术基于电磁诱导透明效应和里德堡原子能级跃迁原理,通过激光激发原子并监测光谱变化来测量微波电场强度。相比传统方法,量子微波测量具有超高灵敏度(理论极限可达nV/cm)、宽动态范围(超过100dB)、小型化等显著优势,且测量结果可直接溯源至普朗克常数。典型实验系统包括光源、原子气室和探测器,采用光谱法、干涉法等多种测量方法。近年来,该技术在基础研究和应用方面取得重要进展,展现出在通信、雷达、计量等

Grow into a more wonderful you 988

「C/C++ 01」 深拷贝和浅拷贝

一、概念 1. 浅拷贝2. 深拷贝3. 深浅拷贝问题4. 总结 二、在C++的类中实现深拷贝 1. 拷贝构造函数 中实现深拷贝2. operator= 中实现深拷贝

look_outs的博客 2983

A类功率放大器

在A类放大器中,导通角是完整的360°或100%的输入信号,而在其他类别的放大器中,晶体管在一个较小的导通角内导通。通过在输出级使用两个互补的晶体管,其中一个晶体管是NPN或N通道类型,而另一个晶体管是PNP或P通道(互补)类型,以所谓的 "推挽 "配置连接,可以获得比A类放大器更大的功率输出和效率。这种类型的电路效率很低(低于30%),而且对直流电源的消耗很大,输出的功率却很小。由于我们感兴趣的是向负载提供最大的交流功率,同时从电源中消耗尽可能少的直流电,所以我们主要关注的是放大器的 "转换效率"。

LSW20072007的博客 2469

超详细Tokenizer——文本训练数据预处理

Tokenizer是Keras库中的一个文本处理工具,它用于将文本分词并构建词汇表,同时将文本映射到整数序列。这对于自然语言处理任务非常有用,例如文本分类、情感分析、机器翻译等。

halo的博客 3701

c++中的复制(深拷贝/浅拷贝/拷贝构造函数/拷贝赋值运算符/移动语义)

移动构造函数的形式为。

zengchenAAA的博客 8662

企业信息化系统的组成模块-核心业务系统

通过标准化的数据流形成完整的业务闭环,CRM生成的销售订单驱动ERP的生产和采购,ERP将生产计划传递给MES执行,MES报工数据返回ERP进行成本核算,ERP再将交付信息同步给CRM供客户查询。生产管理确保高效交付,缩短订单周期。某贸易公司实施ERP供应链模块后,库存周转率从每年4次提升到8次,库存资金占用从2000万降到1200万,释放800万现金流,同时缺货率从15%降到5%。│ │库存 │ │ MRP │ │ ERP │ │ 云ERP/ │ │。

weiyvyy的博客 695

在C++中如何copy一个对象,进行深copy

在C++中如何copy一个对象,进行深copy 修改拷贝后的对象不影响之前的对象,如何操作? 在C++中进

Kp0fS的草稿纸 1622

结构函数详解

C3M系列覆盖从1 kW到60 kW功率范围,器件Rdson低、开关速度快(Eon/Eoff低),支持高温工作(结温高达175–225°C)。型号电压 (V)Rdson (mΩ, 典型@25°C)电流 (A, 连续@25°C)封装类型典型应用功率 (kW)65012022TO-247-41–106506035TO-247-35–2065060355–2012002180TO-247-310–40120016100TO-247-420–601200。

专注于前沿技术的探索与实践,热衷于从代码逻辑、架构设计到行业应用等多维度深挖技术本质。期待在技术之路上与你共同成长~ 158

SAP 采购申请、采购订单的审批策略

采购申请、采购订单的审批策略 采购申请审批 PR审批可以分为:含分类、无分类 1、无分类PR审批: A、后台配置: 设置批准代码(批准代码可以设置多级审批): 发布批准标识使用系统已有的 “2 询价/采购订单”: 新建采购申请审批策略Z1(仅设置1级审批,一共可以设置8级审......

willieyuan的博客 2万+

c++深拷贝(两种)和浅拷贝

文章目录1.深拷贝和浅拷贝2. 移动构造函数(std::move())3.左值和右值 c++的拷贝有两种:即深拷贝和浅拷贝. 1.深拷贝和浅拷贝 在未定义显示拷贝构造函数的情况下,系统会调用默认的拷贝函数——即浅拷贝,它能够完成成员的一一复制。当数据成员中没有指针时,浅拷贝是可行的;但当数据成员中有指针时,如果采用简单的浅拷贝,则两类中的两个指针将指向同一个地址,当对象快结束时,会调用两次析构函数,而导致指针悬挂现象,所以,此时,必须采用深拷贝。 深拷贝与浅拷贝的区别就在于深拷贝会在堆内存中另外申请空间来

Birate的博客 8363

基于MATLAB的多无人机多任务调度算法——CBBA带时间窗

本文将介绍基于MATLAB的CBBA算法,并对其进行改进,加入时间窗概念,以提高多无人机系统的调度效率和性能。时间窗用于限定任务的执行时间范围,以避免任务执行时间过长或过短导致的问题。具体而言,我们为每个任务设置一个允许的最早开始时间和最晚结束时间,并在任务分配的过程中考虑这些时间约束。在多无人机系统中,需要将若干个任务分配给不同的无人机完成,以实现高效的任务执行。以上是关于基于MATLAB的多无人机多任务调度算法CBBA带时间窗的简要介绍和源代码实现。多无人机系统的调度问题。

BUG?不存在的! 1898

C++类对象之间复制,拷贝构造函数的作用,深拷贝与浅拷贝

在C++ 中,当类对象之间相互赋值的时候会存在拷贝的问题。特别是在使用vector对类对象进行管理的时候,这个问题会比较明显。这个时候,定义类的拷贝构造函数就很有作用了。 先说说浅拷贝的情况,代码如下:#include using namespace std; class image { public: int *pImgdata; int width; int height; im

JoliceYu的技术博客 2333

win10 跳过U8环境检测的IE WebControls.rar

win10 安装u8的时候 提示IE WebControls 不通过,这个工具可以欺骗u8的检查。 跳过U8环境检测的IE WebControls。提示导入失败后,重新检测通过。

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

C++类和对象—对象特征(构造函数与析构函数,函数的分类以及调用,拷贝构造函数调用时机,构造函数调用规则,深拷贝和浅拷贝,初始化列表,类对象作为类成员,静态成员)

对象的初始化和清理生活中我们买的电子产品都基本会有出厂在某一天我们不用时候也会删除一些自己信息数据保证安全C++中的面向对象来源于生活,每个对象也都会有初始设置以及 对象销毁前的清理数据的设置。

qq_63055790的博客 270

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

【C++】类和对象 - 构造函数调用规则-深拷贝和浅拷贝-类对象作为类成员

默认情况下,C++编译器至少给一个类添加3个函数。3.默认拷贝构造函数,对属性进行值拷贝。1.默认构造函数(无参,函数体为空)2.默认析构函数(无参,函数体为空)使用默认的拷贝构造函数是浅拷贝。自己实现拷贝构造函数实现深拷贝。

Blablabla_的博客 211

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

C++类对象的复制-拷贝构造函数(深拷贝,浅拷贝)

对于普通类型的对象来说,它们之间的复制是很简单的,例如:int a=88;int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。 #include &lt;iostream&gt;using namespace std; class CExample {private:  int a;public:  CExample(int...

blogfeifei 116

C++拷贝构造函数(深拷贝,浅拷贝)

C++拷贝构造函数(深拷贝,浅拷贝)对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a=88; int b=a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。下面看一个类对象拷贝的简单例子。 #include using namespace std;class CExample { private:  int a; public:

yuxiao2672426816的专栏 226

c++拷贝构造函数

一. 什么是拷贝构造函数 首先对于普通类型的对象来说,它们之间的复制是很简单的,例如: int a = 100; int b = a; 而类对象与普通对象不同,类对象内部结构一般较为复杂,存在各种成员变量。 下面看一个类对象拷贝的简单例子。 #include <iostream> using namespace std; class CExample { privat...

积累点滴,保持自我 7657

C++中返回值为 类对象 详解

C++中返回值为 类对象 详解 代码如下: #include <iostream> using namespace std; //建一个Test类 class Test { public: Test() { a = 0; b = 0; cout << "无参构造函数被调用了" << endl; } Test(int aa, int bb) { a = aa; b = bb; cout << "有参构造函数被调用了" <&

abc 3458
上一篇: C++拷贝构造函数的几个细节
下一篇: C++本质:类的赋值运算符=的重载,以及深拷贝和浅拷贝
chjp2046
博客等级 码龄18年 13粉丝 65原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值