C++拷贝构造函数

c++填空题 5-1 阅读下面的程序,完成其中复制构造函数的代码。 #include <iostream> using namespace std; class CAT { public: CAT(); CAT(const CAT&); ~CAT(); int GetAge() const { return *itsAge; } void SetAge(int age){ *itsAg 阅读详情

摘要:

1.代码格式牢记。类名(const 类名 &X)

2.该函数的三种调用时机。

3.浅拷贝与深拷贝(是否有动态成员变量)。

一、什么是拷贝构造函数

例1:

#include <iostream>  
using namespace std;  

class CExample {  
private:  
	int a;  
public:  
	//构造函数  
	CExample(int b)  
	{ a = b;}  

	//拷贝构造函数  
	CExample(const CExample& C)  
	{  
		a = C.a;  
	}  

	//一般函数  
	void Show ()  
	{  
		cout<<a<<endl;  
	}  
};  

int main()  
{  
	CExample A(100);  
	CExample B = A; // CExample B(A); 也是一样的  
	B.Show ();  
	return 0;  
}   
系统为对象B分配了内存并完成了与对象A的复制过程。就类对象而言, 相同类型的类对象是通过拷贝构造函数来完成整个复制过程的。CExample(const CExample& C)就是我们自定义的拷贝构造函数。可见,拷贝构造函数是一种特殊的构造函数,它 必须的一个参数是本类型的一个引用变量。

二、拷贝构造函数的调用时机

在C++中,下面三种对象需要调用拷贝构造函数!

1.对象以值传递的方式传入函数参数

例2:

#include <iostream>
using namespace std;

class CExample   
{  
private:  
	int a;  

public:  
	//构造函数  
	CExample(int b)  
	{   
		a = b;  
		cout<<"creat: "<<a<<endl;  
	}  

	//拷贝构造  
	CExample(const CExample& C)  
	{  
		a = C.a;  
		cout<<"copy"<<endl;  
	}  

	//析构函数  
	~CExample()  
	{  
		cout<< "delete: "<<a<<endl;  
	}  

	void Show ()  
	{  
		cout<<a<<endl;  
	}  
};  

//全局函数,传入的是对象  
void g_Fun(CExample C)  
{  
	cout<<"test"<<endl;  
}  

int main()  
{  
	CExample test(1);  
	//传入对象  
	g_Fun(test);  
	return 0;  
}  
g_Fun(test) 执行步骤:

①test对象传入形参时,会产生一个临时变量,设为C。

②然后调用拷贝构造函数把test的值给C。

③等g_Fun()执行完成后,析构C对象。

2.对象以值传递的方式从函数返回

例3:

#include <iostream>
using namespace std;

class CExample   
{  
private:  
	int a;  

public:  
	//构造函数  
	CExample(int b)  
	{   
		a = b;  
	}  

	//拷贝构造  
	CExample(const CExample& C)  
	{  
		a = C.a;  
		cout<<"copy"<<endl;  
	}  

	void Show ()  
	{  
		cout<<a<<endl;  
	}  
};  

//全局函数  
CExample g_Fun()  
{  
	CExample temp(0);  
	return temp;  
}  

int main()  
{  
	g_Fun();  
	return 0;  
}  
当g_Fun()函数执行到return时,会产生以下几个重要步骤:

①先会产生一个临时变量,就叫XXXX吧。

②然后调用拷贝构造函数把temp的值给XXXX。整个这两个步骤有点像:CExample XXXX(temp);

③在函数执行到最后先析构temp局部变量。(析构顺序)

④等g_Fun()执行完后再析构掉XXXX对象。

3.对象需要另外一个对象初始化

CExample A(100);  
CExample B = A; 
最后一句会调用拷贝构造函数。
若程序如下,则不会调用拷贝构造函数。即:CExample B = A;与B = A;的区别。

CExample a(1);
CExample b(2);
b = a;
最后一句为调用拷贝构造函数,调用了等号运算符重载。程序代码示例如下(注意其中this与*this区别)

CExample &operator=( const CExample &rhs )
{
	if ( this == &rhs ) {
            return *this;
        }
        this->a = rhs.a;
        return *this;
}

三、浅拷贝与深拷贝

系统自带默认的拷贝构造函数。

1.浅拷贝

只对对象中的数据成员进行简单的赋值。大多数情况下“浅拷贝”已经能很好地工作了,但是一旦对象存在了动态成员,那么拷贝就会出问题了。如下代码:

    class Rect  
    {  
    public:  
        Rect()      // 构造函数,p指向堆中分配的一空间  
        {  
            p = new int(100);  
        }  
        ~Rect()     // 析构函数,释放动态分配的空间  
        {  
            if(p != NULL)  
            {  
                delete p;  
            }  
        }  
    private:  
        int width;  
        int height;  
        int *p;     // 一指针成员  
    };  
      
    int main()  
    {  
        Rect rect1;  
        Rect rect2(rect1);   // 复制对象  
        return 0;  
    }  
error:进行对象复制时,对于动态分配的内容没有进行正确的操作。

在运行定义rect1对象后,由于在构造函数中有一个动态分配的语句,因此执行后的内存情况大致如下:

在使用rect1复制rect2时,由于执行的是拷贝,只是将成员的值进行赋值,这时rect1.p=rect2.p,也即这两个指针指向了堆里的同一个空间,如下如所示:

当然,这不是我们所期望的结果,在销毁对象时,两个对象的析构函数将对同一个内存空间释放两次,这就是错误出现的原因。我们需要的不是两个p有相同的值,而是两个p指向的空间有相同的值。解决办法就是使用“深拷贝”。

2.深拷贝

在“深拷贝”的情况下,对于对象中动态成员,应该重新动态分配空间,如下所示。

    class Rect  
    {  
    public:  
        Rect()      // 构造函数,p指向堆中分配的一空间  
        {  
            p = new int(100);  
        }  
        Rect(const Rect& r)  
        {  
            width = r.width;  
            height = r.height;  
            p = new int;    // 为新对象重新动态分配空间  
            *p = *(r.p);  
        }  
        ~Rect()     // 析构函数,释放动态分配的空间  
        {  
            if(p != NULL)  
            {  
                delete p;  
            }  
        }  
    private:  
        int width;  
        int height;  
        int *p;     // 一指针成员  
    };  
完成对象复制后,内存情况如下所示:

此时rect1的p和rect2的p各自指向一段内存空间,但它们指向的空间具有相同的内容,这就是所谓的“深拷贝”。


参考:

http://blog.youkuaiyun.com/lwbeyond/article/details/6202256

YOLOv11改进入门篇 | 手把手讲解改进模块如何实现高效涨点,以SimAM注意力模块为例 本文记录的是基于SimAM注意力模块的YOLOv11目标检测方法研究。SimAM注意力模块通过优化能量函数来获得每个神经元的三维权重,而或增加计算复杂度。若是有轻量化需求的小伙伴,无参的注意力模块也许是一个不错的选择。 阅读详情

相关推荐

当vCenter的证书过期、Root密码过期、Root密码遗忘同时发生时的解决方法与步骤

vCenter,强制修改root密码,修改SSO User密码,修复证书过期问题

OCTSJimmy的专栏 5551

C++--复制构造函数

测试代码 #include<iostream> using namespace std; class point{ public: point(double a,double b); ~point(); point(point &p); void fun1(point p); point fun2(); double getx() { return x...

海到无边天作岸 山登绝顶我为峰 1782

Robosuite与Robomimic:机器人学习的黄金搭档

本文深入探讨了Robosuite与Robomimic这对机器人学习的黄金组合,详细介绍了如何利用Robosuite进行物理仿真和任务环境构建,以及Robomimic在演示数据处理和离线学习算法实现中的应用。通过实际案例和代码示例,展示了从仿真环境搭建到模型训练的全流程,帮助研究人员高效开展机器人学习实验。

weixin_29178069的博客 415

第六周阅读程序5:复制构造函数运行机制

#include using namespace std; class AA { public: AA(int i,int j) { A=i; B=j; cout<<"Constructor\n"; } AA(AA &obj) { A=obj.A+1;

Destiny_Forever的专栏 603

深入解析MOS管电容特性:从基础理论到高频应用

本文深入解析了MOS管的电容特性,从基础物理结构出发,详细拆解了栅氧电容、重叠电容和结电容的成因与影响。文章重点探讨了电容值随工作状态变化的非线性特性,并分析了其在CMOS高频开关电源、射频电路等应用中的关键作用,包括开关损耗、米勒效应、信号完整性挑战以及如何将电容特性转化为可控元件(如MOS变容管)的机遇。最后提供了从选型、仿真到PCB布局的实战设计指南。

weixin_29278805的博客 382

Python量化交易实战:pytdx库高效获取通达信分笔成交数据

本文详细介绍了如何使用Python的pytdx库高效获取通达信分笔成交数据,为量化交易提供关键市场微观结构分析。通过环境搭建、服务器连接、数据获取与清洗的完整流程,帮助开发者快速掌握这一免费高质量数据源,并实现分笔数据的实战分析与应用。

weixin_29061509的博客 1351

pta c++ 程序填空题

pta c++ 判断题 类与对象 数据共享与保护 数组 指针 字符串 继承与派生 多态性 群体类和群体数据的组织 泛型程序设计 流类库与输入输出 异常处理 stl 面向对象程序设计 成员函数 构造函数 析构函数 类的组合 作用域 静态 动态 友元 常对象 多文件结构 对象数组 this指针 动态内存分配 引用 虚函数 抽象类 运算符重载 函数模板 类模板 容器

weixin_62566689的博客 5054

Oracle19c安装,基本配置教程(超详细)

安装有出错的风险,卸载也是比较麻烦的,所以先提前设置一个还原点,在windows中的步骤如下,如果对自己有信心,可以直接跳过该部分开始安装oracle在设置中进入创建还原点的界面开始创建还原点上面已经成功创建了还原点,如果安装oracle时出现问题,自己也无法解决,恢复到安装之前即可,恢复步骤如下经过上面的步骤,Oracle我们就能够正常使用了,我们就使用自己在sql plus里面创建的账号即可,创建的表会默认存放在我们自己创建的表空间里面。

秃头披风侠的博客 7万+

CPP-基础:C++拷贝构造函数详解

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

dixiongbi7761的博客 147

《BiLSTM with Multi-Polarity Orthogonal Attention for Implicit Sentiment Analysis》论文阅读笔记

文章名:《BiLSTM with Multi-Polarity Orthogonal Attention for Implicit Sentiment Analysis》 作者Jiyao Wei a,1, Jian Liaoa,1, Zhenfei Yanga, Suge Wanga,b,∗, Qiang Zhaoa 年份 2019 1 Introduction 目前文本情感分析多分析带...

weixin_39036944的博客 1631

安装keil5(MDK)及导入pack包教程

首先说明的是我安装的Keil版本为Keil V5.29.0.0 1、安装软件 右键管理员权限运行安装包 设置安装路径以及pack的存放路径 随意输入First Name和E-mail 安装驱动 完成软件安装,然后可以先关闭弹出的Pack Install(一会再添加) 2、激活一下软件 打开桌面的Keil File → License Management(我之前注册过了) 右...

hrx-@@ 10万+

C++——拷贝构造函数

(用旧对象去构造新对象)拷贝构造函数,又称复制构造函数,是一种特殊的构造函数,它由编译器调用来完成一些基于同一类的其他对象的构造及初始化。值类型(不行,会产生递归);指针类型(能实现要求,但会出现歧义(感觉a的地址给b构造));引用类型(本类对象的const引用)。其唯一的形参必须是引用,但并不限制为const,一般普遍的会加上const限制。此函数经常用在函数调用时用户定义类型的值传递及返回。拷贝构造函数要调用基类的拷贝构造函数和成员函数。

weixin_59179454的博客 2万+

【Unity3D框架】GameFramework框架完全教程《全网最全》-专栏文章目录

最近准备学习框架,了解到GameFramework框架是国产Unity3D框架,准备学习一下,但是奈何全网关于这个框架的教程实在太少。为了让自己学习方便一些,也为了让后来者乘凉。将框架以自己的理解整理目录,并且补全教程。觉得教程有帮助别忘了一键三连哦。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 2万+

cpp拷贝构造函数

1.当类含有指针时,必须自定义拷贝构造函数。 坑点: class DoubleTest { double *d; public: DoubleTest() :d(new double(123)) { cout << "constructor" << endl; } //DoubleTest(cons

wjxuanxuan的博客 928

android 蓝牙通讯demo

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

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

C++拷贝构造函数的调用时机

C++拷贝构造函数的调用时机 一、拷贝构造函数调用的时机 ​ 当以拷贝的方式初始化对象时会调用拷贝构造函数,这里需要注意两个关键点,分别是以拷贝的方式和初始化对象 1. 初始化对象 初始化对象是指,为对象分配内存后第一次向内存中填充数据,这个过程会调用构造函数,对象被创建后必须立即初始化。也就是说只要创建对象就会调用构造函数。 2.初始化和赋值的区...

一 6045

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

cpp--拷贝构造函数详解

本文详细解释了cpp中的拷贝构造函数,包括定义和使用方法,也帮大家规避了一些易错点

2302_80295520的博客 1069

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

19 CPP拷贝构造函数

如果类中重载了拷贝构造函数却没有定义默认的拷贝构造函数,编译器会提供默认的拷贝构造函数,这一点和普通构造函数不一样。函数以值的方式返回对象时,可能会调用拷贝构造函数(VS会调用,Linux不会,g++编译器做了优化) 代码说明。但是重载的时候,形参中一定要有类本身的常引用,如果形参中没有类本身的常引用,那就成了普通构造函数。类名(.....,const 类名& 对象名,.....){......}拷贝构造函数可以重载,可以有默认参数。

wade1010的专栏 248

【C++ | 拷贝构造函数】一文了解C++的 拷贝(复制)构造函数

👉本文介绍C++的拷贝构造函数,为什么需要拷贝构造函数,什么是拷贝构造函数,怎么使用拷贝构造函数,默认拷贝构造函数。

wkd_007的博客 9727

C++ —— 拷贝构造函数

C++ —— 拷贝构造函数

MaoSiri的博客 744

C++ 拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。这句话的意思是在利用拷贝构造函数创建一个新的对象时,是通过复制现有对象的数据来初始化新对象。所以说,新对象将成为现有对象的副本。

qq_51753728的博客 918

c++中拷贝构造函数被调用的时机

拷贝构造函数被调用的几种情况: (1)当用类的一个对象去初始化该类的另一个对象时,系统会自动调用拷贝构造函数; (2)将一个对象作为实参传递给一个非引用类型的形参,系统会自动调用拷贝构造函数; (3)从一个返回类为非引用的函数返回一个对象时,系统会自动调用拷贝构造函数; (4)用花括号列表初始化一个数组的元素时,系统会自动调用拷贝构造函数。 下面逐个举例: 1 当用类的一个对象去初始化该类的另一个对象时,系统会自动调用拷贝构造函数 #include<ctime> #include

StudyWinter的博客 7365

C++拷贝构造函数详解

在C++中,拷贝构造函数是一种特殊的构造函数,用于创建一个新对象,并将其初始化为现有对象的副本。拷贝构造函数的函数名必须与类名相同,并且参数为该类的一个常引用。拷贝构造函数是一种特殊的构造函数,用于创建对象的副本。他接受一个同类型的对象(本类对象的引用)作为参数,并使用该对象的数据来初始化新对象。拷贝构造函数通常用于在程序中复制对象,以便在不修改原始对象的情况下对其进行操作。拷贝构造函数通常会执行深拷贝操作,即复制指针指向的数据,而不是仅仅复制指针本身。

m0_62573214的博客 4073

C++默认拷贝构造函数

C++默认拷贝构造函数 转载来源 c++类的中有两个特殊的构造函数,(1)无参构造函数,(2)拷贝构造函数。它们的特殊之处在于: (1)当类中没有定义任何构造函数时,编译器会默认提供一个无参构造函数且其函数体为空; (2)当类中没有定义拷贝构造函数时,编译器会默认提供一个拷贝构造函数,进行成员变量之间的拷贝。(这个拷贝操作是浅拷贝) 这里只讲拷贝构造函数。在c语言中, int a = 5; //...

Meloor的博客 2890
上一篇: C++中static关键字
下一篇: 操作系统常见面试题及答案
hellorichen
博客等级 码龄13年 199粉丝 104原创
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值