大家好
欢迎回来继续学习
C++语言程序设计
下面我们就通过一个具体的例子
来看看什么时候会在程序中
发生复制构造
现在我们来看
在这个例子中
首先定义了一个Point类
就像a
接下来定义对象b的时候
用a去初始化b
那用a去初始化b的时候
我们都应该想得到
这个时候应该要调用
复制构造函数的
也叫拷贝构造函数
再往下看
在这个地方用b作实参
对象作实参
去调用了函数fun1
我们看这个函数fun1
它的形参类型是Point类对象
所以形实结合的时候
用实参去初始化形参的时候
应该也会发生一次复制构造
接下来呢
fun2函数的运行结果
复制给对象b
那我们来看这个fun函数
它的结果是一个什么
是一个Point类对象
它把这个局部对象return
返回给调用者
所以在这个返回的过程中
一个局部对象怎么可能
给到它的调用者去呢
在这个过程中
会发生复制构造
构造一个临时无名对象
传给调用者
现在我首先把程序整个运行一遍
大家看一下这个运行效果
然后我再用单步跟踪的方法
跟大家一起跟踪到函数体内部
去分析这个结果是怎么得出来的
那现在我就在主函数的最后一句
最后一个结束大括号之前
在这儿设一个断点
就在这儿点一下
就设了一个断点
然后按这个功能键f5
它就一下就执行完了
那这个时候呢
如果你不设断点
按f5执行完了
这个执行窗口立刻就关掉了
现在这个窗口留在这儿
我们看到调用了三次constructor
就是复制构造函数
为什么会调用三次
复制构造函数呢
接下来我们就用单步运行的方式
来观察一下
好 现在我们先停止调试
再次进入这个主函数
这回我就不一下运行到底了
按f10
用单步执行的方式
进到主函数中去
再执行一步
单步执行
直接构造完成a
好 接下来呢用a作为参数
去初始化b 构造b
这个时候按f11
进到复制构造函数里面
大家看用a去初始化b
调用了复制构造函数吧 对吧
执行完这个复制构造函数以后
那我们看
当前正在构造的对象b
它的x y值都有了
这个a是一样的
接下来呢
输出这个提示信息
我们会看到很多例题里面
会在构造函数
析构函数里写这样一句话
正在调用拷贝构造函数
或者正在调用构造函数析构函数
初学者看到例题你都写这些东西
觉得干吗呀 有什么意思
干吗要写这个信息
这就是作为例题
为了让你执行这个例题的时候
能够看到流程经过了哪些地方
这些提示信息
也叫做调试信息
作为例题是演示给你看的
那么有些时候做开发的过程中
也会写这些调试信息
那么实质上开发工程师
自己能够看到
程序的流程是怎么样
最后交付用户使用的时候
这个信息是不要保留的了
不要让用户用你的软件
经常看到一会构造函数来了
一会析构函数来了
那个是很讨厌的
好 结束这个以后
我们回到主函数中来
现在验证一下
对象b是不是构造好了
所以也调用x
取出来x值输出一下看
是不是0
其实不用输出
我们从调试的这个窗口里面
局部变量这儿也可以看得到
b对象 它的x值是0
我们再执行一步
好 看到这个输出窗口中
确实输出了一个0在这儿
接下来再往下执行
就是调用函数fun1
这个时候用对象作实参
我们看会发生什么
要跟踪到函数里面
当然我们就按f11了
它并不是一下
进到函数fun1里面去
而是进到了
这个复制构造函数里面
为什么呢
因为你要进到fun1之前
先得完成
这个形实结合的参数传递
先得构造这个形参对象
构造这个形参对象
用实参去初始化它的时候
首先就要调用
Point类的复制构造函数
所以就进到这里面来了
进到这里面来了以后
我们看执行这个复制构造
将参数对象的x值
复制给当前x
将参数对象的y值
复制给当前的y
这个执行完了以后
接下来
我们再按个f11
看一下走到哪儿去了
这个时候才进到fun1
也就是说
参数构造完成了
我们看这个时候形参p
它已经有值了
它的x y都有值了
形实结合完成了
执行完这个以后
回到主函数
再走到下一步呢
这个时候要调用fun2
还是用f11跟踪进去
进到这儿来了
构造一个局部对象a
然后这个时候要返回a
返回a的时候呢
我们要看它会不会追踪到
会不会进入到构造函数里面
去构造一个临时无名对象
那我还在这儿按f11
看它去哪儿
果然进到复制构造函数里面了
来构造一个临时无名对象
那么这个临时无名对象
大家看
完成这个x
p点x复制给x
p点y复制给y
这个完成了以后
它x y都是0了 构造好了
这个时候又输出了一遍
Calling the copy constructor
第三次了
那我们来看这个时候
三次copy constructor都有了
好 再回到主函数中
回到这个fun2中
回到主函数中
现在我们来看这儿写着
fun2的返回值
这个是一个对象
这个对象x等于0 y等于0
接下来还要发生一些赋值
有的同学会误会
是不是把这个对象
赋值给b的时候
也调用了复制构造函数呢
不会的
这是赋值 不是构造
b已经存在了
所以给b赋值
不会调用任何构造函数
但是在第八章中我们还要讲
赋值实际上
也是隐含的有一个函数完成的
叫赋值运算符函数
如果我们只实现
这个对应数据程序
一一对应的这种赋值
我们可以用它默认的功能
像这个我按一下f10
它就赋值过去了
大家看b里面的值现在是0
如果我们学习了第八章以后
想定义一种我们自己希望的
特殊的赋值方式
你也可以写一个函数
叫做赋值运算符函数
来实现这个功能
希望大家有兴趣呢
坚持我们学到第八章
就可以自己定义赋值功能了
好 接下来呢
b点x输出一下
也是验证一下
是不是正确得到了这个值
其实不用验证
我们在这儿看到了
已经是这样了
看一下验证结果
确实输出的是0
这个是正确的
那么通过这个例子呢
我想大家就了解了
这三种情况
第一种情况用a初始化b
第二种情况用对象作为实参
第三种情况
函数返回值是对象
这三种情况下
都会调用复制构造函数