首页 > 其他分享 >为什么需要拷贝构造函数

为什么需要拷贝构造函数

时间:2022-10-09 09:34:35浏览次数:54  
标签:为什么 副本 函数 对象 内存空间 拷贝 构造函数

把参数传递给函数有三种方法,一种是传值,一种是传地址,一种是传引用。传值与其他两种方式不同的地方在于 当使用

传值方式的时候,会在函数里面生成传递参数的一个副本,这个副本的内容是按位从原始参数那里复制过来的,两者的内容是相同的。

当原始参数是一个类的对象时,它也会产生一个对象的副本,此时需要注意:一般对象在创建时都会调用构造函数来进行初始化,但是

在产生对象的副本时如果再执行对象的构造函数,那么这个对象的属性又再恢复到原始状态,这就不是我们希望的了。所以在产生对象

副本的时候,构造函数不会被执行,被执行的是一个默认的默认的拷贝构造函数。

 

  问题原因:

  当函数执行完毕要返回的时候对象副本会执行析构函数,

如果你的析构函数是空的话,也不会发生什么问题,但一般的析构函数都是要完成一些清理工作,如释放指针所指向的内存空间,这时候

可能就会出问题。 譬如:我们在构造函数中为一个指针变量分配了内存,在析构函数中释放给这个指针所指向的内存空间,在把对象传递

给函数至函数结束返回 的这个过程中 首先有一个对象的副本产生了。这个副本也有一个指针,它和原始对象的指针是指向同块内存空间的,

函数返回时,副本对象的析构函数执行了,释放了副本对象中指针指向的内存空间,但是这个内存空间对于原始对象而言还是有效地,

这是第一个问题,后面当原始对象也被销毁的时候,原始对象的析构函数执行,还会对那块已经释放掉的内存空间再次释放,产生严重

错误,这是第二个问题。

  解决方法:

  既然传值有这样的问题,那是否可以使用传地址或者传引用的方式解决这种问题呢?

  事实上传地址和传引用确实可以解决这种问题,但是这并不适用所有的情况,有时我们不希望在函数里面的一些操作会影响到函数外部的变量。

为了解决这种问题,此时就需要用到拷贝构造函数,拷贝构造函数就是在产生副本对象的时候执行的,在拷贝构造函数里面我们申请一个新的内存空间,

这样在副本对象执行析构函数时其释放的就是新的内存空间,从而解决这个问题。

  适用范围:

1. 一个对象以值传递的方式传入函数体

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

3. 一个对象需要通过另外一个对象进行初始化  

  拷贝构造函数不可以改变它所引用的对象,如果可以改变,那么将导致无限循环,如果类中没有显示的声明一个拷贝构造函数,

那么编译器会为你隐式定义一个位拷贝的默认拷贝构造函数

 

  如果不准备使用按值传递对象,那么其实是不需要拷贝构造函数,但是我们如果不写拷贝构造函数,编译器又可能为我们创建一个默认的。

那么如何保证一个对象将永远不会被通过按值传递方式传递呢?

  声明一个私有的拷贝构造函数,甚至不必去定义它,除非成员函数或友元函数需要执行按值传递方式的传递。否则,如果用户试图用按值传递方式传递

或返回对象,编译器将会报错。这是因为拷贝构造函数是私有的。因为已经显示地声明我们接管了这项工作,所以编译器不再创建默认的拷贝构造函数

标签:为什么,副本,函数,对象,内存空间,拷贝,构造函数
From: https://www.cnblogs.com/chentianyu/p/16770992.html

相关文章

  • 电源为什么要加快放电功能!放电原理介绍
    ▼关注公众号:工程师看海▼ 大家好,我是工程师看海。很多负载对电源有上电时序和电压转换速率(压摆率)的要求,比如负载需要多路电源时,这些电源要有先后的上电、下电的顺序,同时......
  • 为什么MOS管要并联个二极管,有什么作用?体二极管的原理
    ▼关注公众号:工程师看海▼MOS管,是MOSFET的缩写,全拼是Metal-Oxide-SemiconductorField-EffectTransistor,翻译过来是金属-氧化物半导体场效应晶体管,根据导电沟道的不同,MOS可......
  • 你的PCB地线走的对吗?为什么要有主地?
    PCBlayout需要丰富的经验和扎实的理论基础支持,还要多踩几个坑,多做几个仿真加深对走线的理解,才能形成闭环的走线设计,今天介绍一个和GND走线相关的案例,在手机领域会影响相机......
  • 为什么负载电流增加时电源电压会下降?
    ​ 大家好,我是工程师看海。在以前的文章中我总是提到当负载电流增加时,电源的输出电压会下降,很多同学在实际项目中也会发现这个现象,有什么危害呢?为什么会有这个现象呢?下图......
  • 为什么说js是单线程?
    为了搞清楚这个问题,我们需要先了解这几个东西:1.什么是线程?什么是进程?他们之间的关系?2.什么是任务队列(EventQueue)?3.什么是事件循环?4.为什么说js是单线程?5.为什么j......
  • 为什么德国造的一把菜刀都这么贵?
    为啥一把菜刀就要五六百?​——细节保证品质说到德国刀具,大家可能都会想到双立人但三叉(Wüsthof)这个牌子据说在欧洲比双立人更有地位三叉的全部产品只在德国生产一套刀具卖到......
  • js高级ES6class构造函数与super继承
    <!DOCTYPEhtml><htmllang="en"><head> <metacharset="UTF-8"> <metahttp-equiv="X-UA-Compatible"content="IE=edge"> <metaname="viewport"content="width=......
  • JavaScript高级复习——构造函数和原型
    构造函数JavaScript的构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的this上添加。通过这两种方式添加的成员,就分别称之为静态成员和实例成员......
  • python写脚本测试执行为什么要写if __name__ == '__main__'
    我的博客在写python脚本的时候,例如,我写一个test1.pydeftest(n):print(n)if__name__=='__main__':n=1test(1)接下来打开cmd命令窗口,执行命令python......
  • [转]为什么VS提示SurfFeatureDetector不是cv的成员函数
    surf和sift算法都是在头文件#include<opencv2/features2d/features2d.hpp>中,但在新的opencv版本出来后,如果仍然使用这个头文件就会出现编译错误如下:'SurfFeatureDetector......