利用类定义一个指针会调用默认构造函数吗_C++的拷贝构造函数

拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象。拷贝构造函数通常用于:

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

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

  • 复制对象,并从函数返回这个对象。

在默认情况下(用户没有定义,但是也没有显式的删除),编译器会自动的隐式生成一个拷贝构造函数和赋值运算符。但用户可以使用delete来指定不生成拷贝构造函数和赋值运算符,这样的对象就不能通过值传递,也不能进行赋值运算。

class Person{public: Person(const Person& p) = delete; Person& operator=(const Person& p) = delete;private: int age; string name;};

上面的定义的类Person显式的删除了拷贝构造函数和赋值运算符,在需要调用拷贝构造函数或者赋值运算符的地方,会提示_无法调用该函数,它是已删除的函数_。
还有一点需要注意的是,拷贝构造函数必须以引用的方式传递参数。这是因为,在值传递的方式传递给一个函数的时候,会调用拷贝构造函数生成函数的实参。如果拷贝构造函数的参数仍然是以值的方式,就会无限循环的调用下去,直到函数的栈溢出。

  • 何时调用

拷贝构造函数和赋值运算符的行为比较相似,都是将一个对象的值复制给另一个对象;但是其结果却有些不同,拷贝构造函数使用传入对象的值生成一个新的对象的实例,而赋值运算符是将对象的值复制给一个已经存在的实例。这种区别从两者的名字也可以很轻易的分辨出来,拷贝构造函数也是一种构造函数,那么它的功能就是创建一个新的对象实例;赋值运算符是执行某种运算,将一个对象的值复制给另一个对象(已经存在的)。调用的是拷贝构造函数还是赋值运算符,主要是看是否有新的对象实例产生。如果产生了新的对象实例,那调用的就是拷贝构造函数;如果没有,那就是对已有的对象赋值,调用的是赋值运算符

调用拷贝构造函数主要有以下场景:

  • 对象作为函数的参数,以值传递的方式传给函数。 

  • 对象作为函数的返回值,以值的方式从函数返回

  • 使用一个对象给另一个对象初始化

代码如下:

class Person{public: Person(){} Person(const Person& p) { cout << "Copy Constructor" << endl; } Person& operator=(const Person& p) { cout << "Assign" << endl; return *this; }private: int age; string name;};void f(Person p){ return;}Person f1(){ Person p; return p;}int main(){ Person p; Person p1 = p; // 1 Person p2; p2 = p; // 2 f(p2); // 3 p2 = f1(); // 4 Person p3 = f1(); // 5 getchar(); return 0;}

上面代码中定义了一个类Person,显式的定义了拷贝构造函数和赋值运算符。然后定义了两个函数:f,以值的方式参传入Person对象;f1,以值的方式返回Person对象。在main中模拟了5中场景,测试调用的是拷贝构造函数还是赋值运算符。执行结果如下:61c697a746e07f15e3cded930d979057.png

分析如下:

  • 这是虽然使用了"=",但是实际上使用对象p来创建一个新的对象p1。也就是产生了新的对象,所以调用的是拷贝构造函数。

  • 首先声明一个对象p2,然后使用赋值运算符"=",将p的值复制给p2,显然是调用赋值运算符,为一个已经存在的对象赋值 。

  • 以值传递的方式将对象p2传入函数f内,调用拷贝构造函数构建一个函数f可用的实参。

  • 这条语句拷贝构造函数和赋值运算符都调用了。函数f1以值的方式返回一个Person对象,在返回时会调用拷贝构造函数创建一个临时对象tmp作为返回值;返回后调用赋值运算符将临时对象tmp赋值给p2.

  • 按照4的解释,应该是首先调用拷贝构造函数创建临时对象;然后再调用拷贝构造函数使用刚才创建的临时对象创建新的对象p3,也就是会调用两次拷贝构造函数。不过,编译器也没有那么傻,应该是直接调用拷贝构造函数使用返回值创建了对象p3。

  • 深拷贝、浅拷贝

说到拷贝构造函数,就不得不提深拷贝和浅拷贝。通常,默认生成的拷贝构造函数和赋值运算符,只是简单的进行值的复制。例如:上面的Person类,字段只有intstring两种类型,这在拷贝或者赋值时进行值复制创建的出来的对象和源对象也是没有任何关联,对源对象的任何操作都不会影响到拷贝出来的对象。反之,假如Person有一个对象为int *,这时在拷贝时还只是进行值复制,那么创建出来的Person对象的int *的值就和源对象的int *指向的是同一个位置。任何一个对象对该值的修改都会影响到另一个对象,这种情况就是浅拷贝。

深拷贝和浅拷贝主要是针对类中的指针动态分配的空间来说的,因为对于指针只是简单的值复制并不能分割开两个对象的关联,任何一个对象对该指针的操作都会影响到另一个对象。这时候就需要提供自定义的深拷贝的拷贝构造函数,消除这种影响。通常的原则是:

  • 含有指针类型的成员或者有动态分配内存的成员都应该提供自定义的拷贝构造函数

  • 在提供拷贝构造函数的同时,还应该考虑实现自定义的赋值运算符

对于拷贝构造函数的实现要确保以下几点:

  • 对于值类型的成员进行值复制

  • 对于指针和动态分配的空间,在拷贝中应重新分配分配空间

  • 对于基类,要调用基类合适的拷贝方法,完成基类的拷贝

d9bc74cdcfd6c9e149022885b4eeb833.png

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

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

相关文章

开发应用层的需要了解 framework层吗?---不需要!!!!

写于2015年12月3日 不同的android版本&#xff0c;不同的framework实现&#xff0c;framework有近2亿行代码&#xff0c;版本越高&#xff0c;代码行数越大&#xff0c;这个过程是很痛苦的。所以不要去学习和阅读framework的源代码。 阅读它的源代码&#xff0c;还不如去学英…

51CTO会员开通成功!开森!

很好&#xff0c;是理想中的学习平台&#xff0c;果断买了&#xff01;^_^ 开森ing 转载于:https://blog.51cto.com/13601545/2324935

一个请求多个响应_一个TCP连接到底可以发多少个HTTP请求?

曾经有这么一道面试题&#xff1a;从 URL 在浏览器被被输入到页面展现的过程中发生了什么&#xff1f;相信大多数准备过的同学都能回答出来&#xff0c;但是如果继续问&#xff1a;收到的 HTML 如果包含几十个图片标签&#xff0c;这些图片是以什么方式、什么顺序、建立了多少连…

手机定位功能为什么打开WiFi(不连接) 就会非常的准 ?如果WiFi 迁到其它地方去了呢?

Wifi定位地图在需要定位的时候&#xff0c;一般会优先用GPS的定位结果&#xff0c;一般来说GPS最准。如果没有GPS的定位结果的话&#xff0c;那一般就退而求其次用Wifi的定位结果。 原理是这样的&#xff1a; 1、手机收集它能够搜索到的Wifi的信息&#xff1b; 2、提交Wifi信…

JxBrowser概述与简单应用

Q&#xff1a;JxBrowser是什么&#xff1f; JxBrowser是一个跨平台的Java库&#xff0c;允许将基于Google Chromium的Web浏览器组件集成到Java Swing / AWT / JavaFX应用程序中。使用JxBrowser&#xff0c;您可以将轻量级Swing / JavaFX组件嵌入到Java应用程序中&#xff0c;以…

我的达内Java培训经历

我当时2009年参加达内培训是在学校里,达内与我们学校合作。当时培训班只开了一个班,有位班主任,因为是第一届,学生也少,不到20个,所以不是老师现场教的,看视频学习的,视频是录播的。班主任负责培训班日常管理工作,和技术答疑。培训视频是投影仪放。当时培训java基础的…

小米大数据:借助Apache Kylin打造高效、易用的一站式OLAP解决方案

如今的小米不仅是一家手机公司&#xff0c;更是一家大数据与人工智能公司。随着小米公司各项业务的快速发展&#xff0c;数据中的商业价值也愈发突显。而与此同时&#xff0c;各业务团队在数据查询、分析等方面的压力同样正在剧增。因此&#xff0c;为帮助公司各业务线解决这些…

旧电脑升级Win11

2014年的联想Y430P升级成功 升级很简单 第一步&#xff1a;下载win11系统安装包&#xff0c;下载地址&#xff1a;系统之家 - Win11系统 第二步&#xff1a;下载KMS激活工具&#xff0c;下载地址&#xff1a;https://www.jb51.net/softs/668522.htmlhttps://www.jb51.net/sof…

进程池的用法

apply() 函数原型&#xff1a; apply(func[, args()[, kwds{}]]) 该函数用于传递不定参数&#xff0c;主进程会被阻塞直到函数执行结束&#xff08;不建议使用&#xff0c;并且3.x以后不在出现&#xff09;。 apply_async() 函数原型&#xff1a; apply_async(func[, args()[, …

巧删无法删除的文件

遇到无法删除的文件&#xff0c;电脑上没有文件粉碎工具&#xff0c;或文件粉碎工具也删不掉&#xff0c;怎么办&#xff1f; 很简单&#xff1a; 把文件的后缀名改掉&#xff0c;比如改成doc&#xff0c;重启电脑&#xff0c;再删除

万用表测线路断点位置_如何测出电线电缆断点在哪?来看看常见的7种方法

实际工程维护检修中&#xff0c;对于维修人员来说最怕的莫过于碰到电线电缆中间断了找不出断点在什么地方。虽然我们弱电工程实际维修的时候&#xff0c;碰到线缆问题会直接想办法换线或者重新敷设&#xff0c;但是我们今天讨论技术上有哪些方法可以测出线缆的断点&#xff01;…

12.04个人博客

地点&#xff1a;自习室 事件&#xff1a;召开小组会议&#xff0c;进项任务分配转载于:https://www.cnblogs.com/qingjia/p/10145891.html

你真的会用OneNote吗?

你真的会用OneNote吗&#xff1f;_程序媛一枚-CSDN博客前言特色功能图片转文字TAB制表符新建表格表格嵌套自动编号保存微信文稿树形目录基本功能总结前言使用OneNote做笔记已经有一年多的时间了&#xff0c;从最开始的抵触&#xff0c;到现在的习惯&#xff0c;心态的转变主要是…

乐学python_铁乐学python_day01-作业

第一题&#xff1a;使用while循环输入 1 2 3 4 5 6 8 9 10# 使用while循环输入 1 2 3 4 5 6 8 9 10count 0while (True) :count count 1#判断当count等于7的时候&#xff0c;返回循环最初&#xff0c;不执行下面的打印等语句if count 7:continueprint (count)#判断当count等…

大道至简: 拉新、促活和留存

互联网运营中的拉新、促活和留存思维&#xff0c;从来不局限于互联网产品里&#xff0c;在传统行业里也是通用的&#xff0c;比如一家理发店的经营也是如此。 互联网运营中的拉新、促活和留存思维&#xff0c;从来不局限于互联网产品里&#xff0c;在传统行业里也是通用的。比如…

python3的pyqt5 qtablewidget按数据大小排列_InnoDB为什么要选择B+树来存储数据?

关于InnoDB索引&#xff0c;我们可能知道InnDB索引是用B树实现的&#xff0c;而B树就是一种能优化查询速度的数据结构。但我们又没想过这样一个问题&#xff0c;能优化查询速度的数据结构有很多&#xff0c;为什么InnoDB要采用B树&#xff1f;常见优化查询速度数据结构哈希表哈…

数据仓如何支撑应用?

数据仓支撑应用&#xff0c;主要有以下步骤&#xff1a; 1.应用部门&#xff1a;在“宁波市公共数据目录平台”按需申请省市共享数据&#xff0c;申请的表审批通过后&#xff0c;提交《审批通过的表清单》给大数据中心&#xff1b; 2.大数据中心&#xff1a;比对《审批通过的…

辛苦俩月总结的面试题,掌握它怼翻面试官不是梦~

小编经过一个多月的不懈努力&#xff0c;给大家总结了一份面试方面的题目。这份面试题涉及高并发、分布式、高可用相关知识点&#xff0c;在此分享给大家&#xff0c;希望大家能拿到一份理想的 Offer&#xff01;因为是笔试题目&#xff0c;大家可以先做。如果需要查看答案&…

python坐标转化极坐标_python 坐标系

广告关闭提供包括云服务器&#xff0c;云数据库在内的50款云计算产品。打造一站式的云产品试用服务&#xff0c;助力开发者和企业零门槛上云。写在前面的话01 今天资源君带大家学习一下python的可视化&#xff0c;何谓可视化呢&#xff1f; 我们常常听说python的数据分析&#…