利用类定义一个指针会调用默认构造函数吗_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,一经查实,立即删除!

相关文章

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

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

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

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

小米大数据:借助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…

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

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

你真的会用OneNote吗?

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

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

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

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

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

百家号 不被推荐,原因:将旧闻冒充新闻发布,请修改后重新发布

1.情景展示 在百家号进行创作的作者&#xff0c;发布文章时&#xff0c;难免会遇到审核不通过&#xff0c;下面说一下其中一种情况&#xff1a; 不被推荐&#xff0c;原因&#xff1a;将旧闻冒充新闻发布&#xff0c;请修改后重新发布. 2.解决方案 出现这种情况&#xff0c;原…

java字符串常量池——字符串==比较的一个误区

转自&#xff1a;https://blog.csdn.net/wxz980927155/article/details/81712342 起因 再一次js的json对象的比较中&#xff0c;发现相同内容的json对象使用比较并不相等。 例如&#xff1a; var obj {}; var obj2 {}; console.log(obj obj2); // 结果为false json在js中代表…

java注解_Java注解教程及自定义注解

Java注解提供了关于代码的一些信息&#xff0c;但并不直接作用于它所注解的代码内容。在这个教程当中&#xff0c;我们将学习Java的注解&#xff0c;如何定制注解&#xff0c;注解的使用以及如何通过反射解析注解。Java1.5引入了注解&#xff0c;当前许多java框架中大量使用注解…

Git设置忽略eclipse配置文件

概述 eclipse的配置文件是不能公用的&#xff0c;不同电脑上的eclipse配置文件内容是不一样的&#xff0c;如果将eclipse配置文件上传到了git&#xff0c;其他开发下载后&#xff0c;导入项目&#xff0c;有些报错就是因为配置文件关系 操作 在git的忽略文件“.gitignore”里…

jdk安装包_第一章(第1节):安装JDK

对于 jdk 的安装&#xff0c;网上有很多种图文解说&#xff0c;但是老鸟发现它们大都不严谨&#xff0c;非常不适合小白。本节课&#xff0c;老鸟就给大家做个小白教程&#xff0c;无论你多么菜&#xff0c;你一定可以安装上&#xff0c;否则你加我微信&#xff0c;我给你打五毛…

eclipse 国内镜像高速下载

概述 eclipse是优秀的老牌IDE&#xff0c;使用eclipse是一种身份的象征&#xff0c;代表了老程序员。eclipse每年都会更新&#xff0c;也越来越好用。但下载的时候&#xff0c;速度一直有点慢&#xff0c;eclipse官网提供了国内镜像&#xff0c;下载很快。 操作步骤 第一步&…

matlab图像去毛刺_警微圈 图像处理第三讲CLAHE

警微圈图像处理100讲 第三讲《限制对比度自适应直方图均衡化》- 圈语 -为给圈粉们提供一些结合公安工作的实用图像处理方法&#xff0c;小编为大家准备了一些程序处理算法(附带代码)。小编使用的图像处理软件是matlab(该软件关注警微圈后台回复“matlab”即可获得下载资源)&…

Microsoft Project 变更项目日历的注意事项

场景 今天在修改一份mpp排期计划里的项目日历&#xff0c;日历是设置了周末2天加班&#xff0c;变更后发现&#xff0c;排期缩短的天数不对。一开始以为是Project软件出问题了&#xff0c;与windows11不兼容&#xff0c;重启了电脑&#xff0c;重试后还是这样&#xff0c;后来…

第十九节TypeScript 模块

1、TypeScript模块&#xff1a; 模块是在其自身的作用域里执行&#xff0c;并不是在全局作用域&#xff0c;这意味着定义在模块里面的变量、函数和类等在模块外部是不可见的&#xff0c;除非明确地使用 export 导出它们。类似地&#xff0c;我们必须通过 import 导入其他模块导…

微软宣布 Edge 浏览器将切换至 Chromium 内核

简述 据微软官方 blog的消息&#xff0c;windows 的默认浏览器 Edge将切换内核至 Chromium&#xff0c;并且微软将秉承开源精神&#xff0c;在未来更多的为 Chromium项目贡献代码。 微软具体说了什么&#xff1f; 原文如下&#xff1a; For the past few years, Microsoft has …

解决the resource is not on the build path of a java project

场景 普通的Java project 转maven 项目后&#xff0c;导入类提示&#xff1a;the resource is not on the build path of a java project 解决方法 将检查java build source&#xff0c;将报错的删除&#xff0c;重新添加src资源包