复制构造函数(拷贝构造函数)
在C++中,下面三种对象需要拷贝的情况。因此,拷贝构造函数将会被调用。
1). 一个对象以值传递的方式传入函数体
2). 一个对象以值传递的方式从函数返回
3). 一个对象需要通过另外一个对象进行初始化
以上的情况需要拷贝构造函数的调用。如果在前两种情况不使用拷贝构造函数的时候,就会导致一个指针指向已经被删除的内存空间。对于第三种情况来说,初始化和赋值的不同含义是构造函数调用的原因。事实上,拷贝构造函数是由普通构造函数和赋值操作赋共同实现的。描述拷贝构造函数和赋值运算符的异同的参考资料有很多。
拷贝构造函数不可以改变它所引用的对象,其原因如下:当一个对象以传递值的方式传一个函数的时候,拷贝构造函数自动的被调用来生成函数中的对象。如果一个对象是被传入自己的拷贝构造函数,它的拷贝构造函数将会被调用来拷贝这个对象这样复制才可以传入它自己的拷贝构造函数,这会导致无限循环。
除了当对象传入函数的时候被隐式调用以外,拷贝构造函数在对象被函数返回的时候也同样的被调用。换句话说,你从函数返回得到的只是对象的一份拷贝。但是同样的,拷贝构造函数被正确的调用了,你不必担心。
如果在类中没有显式的声明一个拷贝构造函数,那么,编译器会私下里为你制定一个函数来进行对象之间的位拷贝(bitwise copy)。这个隐含的拷贝构造函数简单的关联了所有的类成员。许多作者都会提及这个默认的拷贝构造函数。注意到这个隐式的拷贝构造函数和显式声明的拷贝构造函数的不同在于对于成员的关联方式。显式声明的拷贝构造函数关联的只是被实例化的类成员的缺省构造函数除非另外一个构造函数在类初始化或者在构造列表的时候被调用。
拷贝构造函数是程序更加有效率,因为它不用再构造一个对象的时候改变构造函数的参数列表。设计拷贝构造函数是一个良好的风格,即使是编译系统提供的帮助你申请内存默认拷贝构造函数。事实上,默认拷贝构造函数可以应付许多情况。
对一个简单变量的初始化方法是用一个常量或变量初始化另一个变量,例如:
int m = 80;int n = m;
我们已经会用构造函数初始化对象,那么我们能不能象简单变量的初始化一样,直接用一个对象来初始化另一个对象呢?答案是肯定的。我们以前面定义的Point类为例:
Point pt1(15, 25);Point pt2 = pt1;
后一个语句也可以写成:
Point pt2( pt1);
它是用pt1初始化pt2,此时,pt2各个成员的值与pt1各个成员的值相同,也就是说,pt1各个成员的值被复制到pt2相应的成员当中。在这个初始化过程当中,实际上调用了一个复制构造函数。当我们没有显式定义一个复制构造函数时,编译器会隐式定义一个缺省的复制构造函数,它是一个内联的、公有的成员,它具有下面的原型形式:
Point:: Point (const Point &);
可见,复制构造函数与构造函数的不同之处在于形参,前者的形参是Point对象的引用,其功能是将一个对象的每一个成员复制到另一个对象对应的成员当中。
虽然没有必要,我们也可以为Point类显式定义一个复制构造函数:
Point:: Point (const Point &pt){xVal=pt. xVal;yVal=pt. yVal;}
如果一个类中有指针成员,使用缺省的复制构造函数初始化对象就会出现问题。为了说明存在的问题,我们假定对象A与对象B是相同的类,有一个指针成员,指向对象C。当用对象B初始化对象A时,缺省的复制构造函数将B中每一个成员的值复制到A的对应的成员当中,但并没有复制对象C。也就是说,对象A和对象B中的指针成员均指向对象C,实际上,我们希望对象C也被复制,得到C的对象副本D。否则,当对象A和B销毁时,会对对象C的内存区重复释放,而导致错误。为了使对象C也被复制,就必须显式定义复制构造函数。下面我们以string类为例说明,如何定义这个复制构造函数。
我们也常用无名对象初始化另一个对象,例如: |
Point pt = Point(10, 20);
类名直接调用构造函数就生成了一个无名对象,上式用左边的无名对象初始化右边的pt对象。
构造函数被调用通常发生在以下三种情况,第一种情况就是我们上面看到的:用一个对象初始化另一个对象时;第二种情况是当对象作函数参数,实参传给形参时;第三种情况是程序运行过程中创建其它临时对象时。下面我们再举一个例子,就第二种情况和第三种情况进行说明:
Point foo(Point pt) { … return pt;}void main(){Point pt1 = Point(10, 20);Point pt2;…pt2=foo(pt);…}
在main函数中调用foo函数时,实参pt传给形参pt,将实参pt复制给形参pt,要调用复制构造函数,当函数foo返回时,要创建一个pt的临时对象,此时也要调用复制构造函数。
缺省的复制构造函数
在类的定义中,如果没有显式定义复制构造函数,C++编译器会自动地定义一个缺省的复制构造函数。下面是使用复制构造函数的一个例子:
例10-12 | |
|
|
类withCC有一个复制构造函数,类woCC和类composite都没有显式定义复制构造函数。如果在类中没有显式定义复制构造函数,则编译器将自动地创建一个缺省的构造函数。不过在这种情况下,这个构造函数什么也不作。
类composite既含有withCC类的成员对象又含有woCC类的成员对象,它使用无参的构造函数创建withCC类的对象WITHCC(注意内嵌的对象WOCC的初始化方法)。
在main()函数中,语句:
composite c2 = c;
通过对象C初始化对象c2,缺省的复制构造函数被调用。
最好的方法是创建自己的复制构造函数而不要指望编译器创建,这样就能保证程序在我们自己的控制之下。
转载于:https://www.cnblogs.com/lgh1992314/archive/2012/11/18/5835307.html
复制构造函数(拷贝构造函数)相关推荐
- Cherno C++ P44 C++的复制与拷贝构造函数
YouTube视频链接 C++的复制与拷贝构造函数 本文是ChernoP44视频的学习笔记. 看如下代码,a和b是两个独立的变量,它们有不同的内存地址,若将b=3则a仍然是2.在Vector2类中 ...
- 什么是拷贝构造函数?拷贝构造函数何时被调用
1.什么是拷贝构造函数: CA(const CA& C)就是我们自定义的拷贝构造函数.可见,拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变 ...
- 【C++】构造函数 无参构造函数 有参构造函数 拷贝构造函数内联函数
文章目录 函数的定义 函数的的使用方法 函数的返回值 值传递 指针传递 引用传递 C++引用作为函数返回值 函数重载(Function Overloading) 运算符重载(Operator Over ...
- C++编程思想 第1卷 第11章 引用和拷贝构造函数 拷贝构造函数 拷贝构造函数
编译器对如何从现有的对象产生新的对象进行了假定. 当通过按值传递的方式传递一个对象时,就创立了一个新对象,函数体内的 对象是由函数体外的原来存在的对象传递的 编译器假定我们想使用位拷贝来创建对象 每当 ...
- C++ 复制构造函数或者拷贝构造函数
复制构造函数 是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象. 复制构造函数通常用于: 通过使用另一个同类型的对象来初始化新创建的对象. 复制对象把它作为参数传 ...
- [ C++ ] — 拷贝构造函数(复制构造函数)
拷贝构造函数 拷贝构造函数就是用 同一类型的对象复制成员值来初始化对象(当出现类的 "=" 赋值时,就会调用拷贝构造函数) 简单来说,拷贝构造函数就是来复制对象的 默认拷贝构造函数 ...
- C++ 笔记(17)— 类和对象(构造函数、析构函数、拷贝构造函数)
1. 构造函数 构造函数是一种特殊的函数(方法),在根据类创建对象时被调用.构造函数是一种随着对象创建而自动被调用的函数,它的主要用途是为对象作初始化. 构造函数的名称与类的名称是完全相同的,并且不会 ...
- C++——拷贝构造函数
拷贝构造函数 拷贝构造函数是一种特殊的构造函数,它在创建对象时,是使用同一类中之前创建的对象来初始化新创建的对象.拷贝构造函数通常用于: 通过使用另一个同类型的对象来初始化新创建的对象. 复制对象把它 ...
- 拷贝构造函数的调用以及浅拷贝与深拷贝的理解
今天一直在研究拷贝构造函数相关的东西,我这个大四老狗感觉又回到了大一学C++的时候.瞎捣鼓了一天,略微还是有些收获的,趁着脑子中的概念正热,把自己的心得赶紧整理出来分享给大家. 首先简 ...
- 构造函数,拷贝构造函数,赋值函数
C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法.下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个 ...
最新文章
- boost::describe模块实现overloaded的测试程序
- 博览安全圈:360曝Office高危漏洞 微软及时修复
- 简单介绍VS2015自动测试工具
- 最长单调子序列及计数(poj1952)
- 产品经理必懂的技术那点事儿 pdf_产品经理10大基础技能(5):读透神经网络和机器学习...
- (73)FPGA面试题-Verilog实现5人表决器
- kafka python教程_由Flink与Kafka实践探究Kafka的两个问题
- Java基础(五)——泛型
- Python RE模块中search()和match()的区别
- 只需5分钟-----手把手教你如何注册美国AppleId账号
- 看懂财务报表一资产负债表
- win 10 虚拟机设置固定 ip
- Confluence 摘要(Excerpt)宏
- 玩转四旋翼无人机(仿真)
- 了解什么是架构基本概念和架构本质
- 雅思机考经验和考试内容(上海机考中心20191208)
- 自定义UDF函数和UDTF函数
- 用计算机解决问题时 为什么要用计算思维,在问题解决活动中培养计算思维
- 深入理解黑客攻击-键盘记录器
- 更改cognos upfront 的外观
热门文章
- Geth 控制台使用及 Web3.js 使用实战
- 远程桌面怎么持续连接_如何拥有成功且可持续的远程产品管理职业
- 国内使用dropbox_通过创建费用管理器来学习使用Dropbox API
- python如何编写数据库_如何在几分钟内用Python编写一个简单的玩具数据库
- docker容器虚拟化技术_Docker,虚拟机和容器的全面介绍
- unity水管工_我是如何从30岁的管道工转变为32岁的Web开发人员的
- arch linux安装_如何从头开始安装Arch Linux
- Servlert接口的doGet()、doPst()方法
- record-09 ATM 过程思想 综合练习
- 使用工作集(Working Set)整理项目