【C++】类和对象(5)--拷贝构造函数

news2024/11/28 0:33:55

目录

一 概念

二 拷贝构造函数特性

1. 重载形式

2. 参数原则

3 默认拷贝函数

三 拷贝构造函数的实现


一 概念

在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?

class Date
{
public:
       Date(int year = 1900, int month = 1, int day = 1)//默认构造函数
       {
              _year = year;
              _month = month;
              _day = day;
       }

       
       void Print()
       {
              cout << _year << "/" << _month << "/" << _day << endl;
       }

private:
       int _year;
       int _month;
       int _day;
};


class Stack
{
public:
       Stack(size_t capacity = 3)
       {
              cout << "Stack(size_t capacity = 3)" << endl;

              _a = (int*)malloc(sizeof(int) * capacity);
              if (nullptr == _a)
              {
                      perror("malloc申请空间失败!!!");
              }

              _capacity = capacity;
              _top = 0;
       }

       ~Stack()
       {
              cout << "~Stack()" << endl;

              free(_a);
              _capacity = _top = 0;
              _a = nullptr;
       }

private:
       int* _a;
       int _capacity;
       int _top;
};


//值拷贝浅拷贝
void func1(Date d)//形参是实参拷贝
{
       d.Print();
}

void func2(Stack st)//这样拷贝这是不行的
{
       //...
}

int main()
{
       Date d1(2023, 10, 22);
       func1(d1);

       Stack st1;
       func2(st1);

       return 0;
}

 我们可以看到Date类就能传参 但是Stack类就不行, 这涉及到了浅拷贝, 深拷贝

如何解决?

规定, 自定义类型对象拷贝的时候, 调用一个函数, 这个函数就叫拷贝构造

拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存 在的类类型对象创建新对象时由编译器自动调用

拷贝构造函数通常用于:

• 通过使用另一个同类型的对象来初始化新创建的对象。

• 复制对象把它作为参数传递给函数。

• 复制对象,并从函数返回这个对象。
class Date
{
public:
	Date(int year = 1900, int month = 1, int day = 1)//默认构造函数
	{
		_year = year;
		_month = month;
		_day = day;
	}

private:
	int _year;
	int _month;
	int _day;
};


void func1(Date d)//调用拷贝构造 -->形参是实参的拷贝
{
	/*
	(1).d1对象传入形参时,会先会产生一个临时变量,就叫 d。
	(2).然后调用拷贝构造函数把d1的值给d。 整个这两个步骤有点像:Date d(d1);
	(3).等func1()执行完后, 析构掉 d 对象。
	*/
}

Date func2()
{
	Date d2(2023, 11, 20);
	return d2;//调用拷贝构造
	/*
	(1).先会产生一个临时变量,就叫XXXX吧。
	(2).然后调用拷贝构造函数把d2的值给XXXX。整个这两个步骤有点像:Date XXXX(d2);
	(3).在函数执行到最后先析构d2局部变量。
	(4).等func2()执行完后再析构掉XXXX对象。
	*/
}

int main()
{
	Date d1(2023, 10, 22);
	func1(d1);
	Date d3(d1); //调用拷贝构造
	Date d4 = d1;//调用拷贝构造
	return 0;
}

二 拷贝构造函数特性

拷贝构造函数也是特殊的成员函数,其特征如下:

1. 重载形式

拷贝构造函数是构造函数的一个重载形式。

class Date
{
public:
    Date(int year = 1900, int month = 1, int day = 1)
    {
        _year = year;
        _month = month;
        _day = day;
    }
    // Date(const Date d)--> 错误写法:编译报错,会引发无穷递归
    Date(const Date& d) 
    {
        _year = d._year;
        _month = d._month;
        _day = d._day;
    }
private:
    int _year;
    int _month;
    int _day;
};
int main()
{
    Date d1;
    Date d2(d1);//将d1拷贝给d2
    return 0;
}

2. 参数原则

拷贝构造函数的参数只有一个且必须是类类型对象的引用

使用传值方式编译器直接报错, 因为会引发无穷递归调用。

 

3 默认拷贝函数

若未显式定义,编译器会生成默认的拷贝构造函数。 默认的拷贝构造函数对象按内存存储按 字节序完成拷贝,这种拷贝叫做浅拷贝,或者值拷贝

前面已经说了Date类就用编译器生成的默认拷贝构造函数就可以了 不用显示定义构造函数了

注意:类中如果没有涉及资源申请时,拷贝构造函数是否写都可以;一旦涉及到资源申请 时,则拷贝构造函数是一定要写的,需要深度拷贝,否则就是浅拷贝

三 拷贝构造函数的实现

像栈 这些涉及到了资源的申请, 那就需要深度拷贝了

class Stack
{
public:
       Stack(size_t capacity = 3)
       {
              cout << "Stack(size_t capacity = 3)" << endl;

              _a = (int*)malloc(sizeof(int) * capacity);
              if (nullptr == _a)
              {
                      perror("malloc申请空间失败!!!");
              }

              _capacity = capacity;
              _top = 0;
       }

       // Stack st2(st1);
       Stack(const Stack& stt)
       {
              cout << " Stack(Stack& stt)" << endl;
              // 深拷贝
              _a = (int*)malloc(sizeof(int) * stt._capacity);
              if (_a == nullptr)
              {
                      perror("malloc fail");
                      exit(-1);
              }
              memcpy(_a, stt._a, sizeof(int) * stt._top);
              _top = stt._top;
              _capacity = stt._capacity;
       }

       ~Stack()
       {
              cout << "~Stack()" << endl;

              free(_a);
              _capacity = _top = 0;
              _a = nullptr;
       }

private:
       int* _a;
       int _capacity;
       int _top;
};

class MyQueue
{
       Stack _pushst;
       Stack _popst;
       int _size = 0;
};


void func2(Stack st)
{
       //...
}

int main()
{
       Stack st1;
       func2(st1);
       Stack st2(st1);

       MyQueue q1;
       MyQueue q2(q1);

       return 0;
}

总结:

Date 和 MyQueue 默认生成拷贝就可以用        

1、内置类型成员完成值拷贝        

2、自定义类型成员调用这个成员的拷贝构造        

Stack需要自己写拷贝构造,完成深拷贝   顺序表、链表、二叉树等等的类,都需要深拷贝 

本节难度比较简单, 但是对基础性要求较强, 对构造函数还有不太懂的朋友可以去我的博客:

【C++】类和对象(2)--构造函数-CSDN博客

继续加油!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1216388.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

nestJs 高阶用法

真正的服务器需要做全局的数据核查、敏感操作落库和数据转化。 拥有这些能力才能让后台能力更加丰富&#xff0c;本篇将主要使用 NestJs 的高级能力&#xff0c;来实现这些功能。 使用 guards 和 decorators 实现数据校验核查通过 interceptors 和 decorators 实现敏感操作录…

Linux三剑客:grep的基本使用

目录 grep介绍 什么是grep和egrep 使用grep 命令格式 命令功能 命令参数 grep配合正则表达式使用 认识正则 基本正则表达式 匹配字符 配置次数 位置锚定&#xff1a;定位出现的位置 分组和后向引用 作为学习一名计算机专业的学生&#xff0c;我想Linux应该需要了解…

详细自动化测试介绍

&#x1f4e2;专注于分享软件测试干货内容&#xff0c;欢迎点赞 &#x1f44d; 收藏 ⭐留言 &#x1f4dd; 如有错误敬请指正&#xff01;&#x1f4e2;交流讨论&#xff1a;欢迎加入我们一起学习&#xff01;&#x1f4e2;资源分享&#xff1a;耗时200小时精选的「软件测试」资…

【10套模拟】【5】

关键字&#xff1a; 数据的最小单位、归并排序&#xff08;两两归并&#xff09;、单链表顺序存取、邻接表表头顶点顺序存储随机访问、三角矩阵元素个数、堆的性质、冒泡排序、二叉树是否相同

我对需求分析的理解

一、背景 最近做了一个项目&#xff0c;也算是踩坑过程&#xff0c;产品上线了&#xff0c;用户不怎么买单&#xff0c;使用者聊聊无几&#xff0c;前期一直不清楚为什么会这样&#xff0c;诚然新系统的开发设计上采用了更新的技术&#xff0c;设计上采用了更好的理念&#xf…

知识梳理到了领域榜一,意外,开心。

我的护城河 就是掌握的不断更新的技术。 一直被认可的能力。 完美的项目交付。 写的文章得到了读者们的认可。 希望我做的努力被更多的人看到。 分享的代码片可以解决他人的问题。 很惊喜&#xff0c;今早我的文章被数据结构和算法领域内容榜排到了第一名。 被认可的感觉很棒。…

Python-pptx教程之二操作已有PPT模板文件

文章目录 简单的案例找到要修改的元素修改幻灯片中的文本代码使用示例 修改幻灯片的图片代码使用示例 删除幻灯片代码使用示例 获取PPT中所有的文本内容获取PPT中所有的图片总结 在上一篇中我们已经学会了如何从零开始生成PPT文件&#xff0c;从零开始生成较为复杂的PPT是非常消…

【重点文章】服务升级惨痛教训

文章目录 事故解析:避免方法涉及知识 以前怎么接触过大表&#xff0c;所以alter操作我都是一次性执行好几条的&#xff0c;这几条一下子干过去了   结果就是一直在转圈执行&#xff0c;因为alter产生的是表级排它锁&#xff0c;所以有关这几个表的查询更新操作全部处于阻塞…

04-学成在线之系统管理服务模块之查询数据字典表中的内容,前后端联调测试

前后端联调 配置前端环境 实际开发中先由后端工程师将接口设计好并编写接口文档并交给前端工程师&#xff0c;前后端的工程师就开始并行开发 前端开发人员先自己mock数据即使用假数据进行开发,当后端代码完成后前端工程师尝试请求后端接口获取数据然后渲染到页面 第一步: 首…

大力说企微第一课:企业微信的注册验证和认证

这段时间有好几个朋友问我&#xff0c;怎么用企业微信&#xff0c;还有一些朋友反馈&#xff0c;企业微信使用起来不太方便。 在我的印象中&#xff0c;企业微信确实不如微信那么简单&#xff0c;毕竟用户对象是企业&#xff0c;是企业就有多个部门&#xff0c;就有流程&#x…

ubuntu20源码编译搭建SRS流媒体服务器

第一、下载源码 下载源码&#xff0c;推荐用Ubuntu20&#xff1a; git clone -b develop https://gitee.com/ossrs/srs.git第二、编译 2.1、切换到srs/trunk目录&#xff1a; cd srs/trunk2.2、执行configure脚本 ./configure2.3、执行make命令 make2.4、修改conf/rtmp.c…

零代码实现问卷网与巨量引擎的对接

通过数环通&#xff0c;您可以使用不到几分钟的时间即可实现问卷网与巨量引擎的对接与集成&#xff0c;从而高效实现工作流程自动化&#xff0c;降本增效&#xff01; 1.产品介绍 巨量引擎是字节跳动旗下的营销服务品牌&#xff0c;它整合了字节跳动旗下的产品及海量内容&…

简单高效的定制移动固态硬盘,稳定易用的办公小助手

我在平时的工作中&#xff0c;常常需要处理各种大文件和数据&#xff0c;如果硬盘速度跟不上&#xff0c;那工作效率就会大幅降低。今年固态硬盘的价格大幅下降&#xff0c;有很多国产品牌加入其中&#xff0c;很容易找到一款性价比高的固态硬盘&#xff0c;搭配硬盘盒使用&…

mac清除所有数据,不抹除的情况下如何实现?

mac清除所有数据是一个比较复杂的任务&#xff0c;尤其是在不进行系统抹除的情况下。但是&#xff0c;如果你想要将mac完全恢复到出厂设置的状态&#xff0c;同时保留数据&#xff0c;本文将介绍一些可行的方法&#xff0c;帮助您在不抹除硬盘数据的情况下&#xff0c;让mac清除…

Ganache结合内网穿透实现远程不同局域网公网访问

文章目录 前言1. 安装Ganache2. 安装cpolar3. 创建公网地址4. 公网访问连接5. 固定公网地址 正文开始前给大家推荐个网站&#xff0c;前些天发现了一个巨牛的 人工智能学习网站&#xff0c; 通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。 点击跳转到网站…

Zookeeper Java 开发,自定义分布式锁示例

文章目录 一、概述二、导入依赖包三、创建锁的过程3.1 通过 create 创建节点信息3.2 AsyncCallback.StringCallback 回调函数3.3 AsyncCallback.Children2Callback 的回调函数3.4 Watcher 的回调函数 四、完整示例4.1 完整分布式锁代码4.2 测试类 如果您还没有安装Zookeeper请看…

Shopee选品工具软件——知虾,助您轻松把握市场趋势

在如今竞争激烈的电商市场中&#xff0c;了解市场趋势和数据分析是成功的关键。对于Shopee虾皮平台上的商家来说&#xff0c;知虾是一款强大的选品工具软件&#xff0c;它提供了全面的数据分析服务&#xff0c;帮助商家快速了解大盘走势&#xff0c;并挖掘潜力行业类目。本文将…

[msg_msg] corCTF2021 -- fire_of_salvation

前言 msg_msg 是 kernel pwn 中经常用作堆喷的结构体. 其包含一个 0x30 大小的 header. 但 msg_msg 的威力远不如此, 利用 msg_msg 配合其他堆漏洞可以实现任意地址读写的功能. 程序分析 本题给了源码, 可以直接对着源码看. 并且题目给了编译配置文件, 所以可以直接编译一个…

C 语言指针和数组

C 语言指针和数组 在本教程中&#xff0c;您将了解C语言编程中数组与指针之间的关系。您还将学习使用指针访问数组元素。 在了解数组与指针之间的关系之前&#xff0c;请确保检查以下两个主体&#xff1a; [C 数组](C 语言数组-CSDN博客)[C 指针](C 语言指针-CSDN博客) 数组…

2023上海国际电力电工展盛大举行 规模创新高 与行业「升级、转型、融合」

由中国电力企业联合会、国家电网主办及雅式展览服务有限公司承办的「第三十一届上海国际电力设备及技术展览会 (EP Shanghai 2023)」从11月15日起至17日一连三天于上海新国际博览中心盛大举行&#xff0c;并首度增设专题子展「上海国际储能技术应用展览会」。本届展会以“升级、…