关于 C++ 拷贝构造函数(copy constructor)中的形参必须为引用类型的详解

在《C++ primer》中文第四版中,关于拷贝构造函数(也称复制构造函数)是这样定义的:是一种特殊构造函数,具有单个形参,该形参(常用const修饰)是对该类类型的引用。

问题来了!为什么形参必须为该类类型的引用?而不能是值传递方式?(PS:其实传值和传址都可以统一为传值,前者传的是对象的值,后者传的是对象的地址的值)

先看下边两组代码:

1、

 1 class Example {
 2
 3  public:
 4
 5       Example() {}
 6
 7       Example(const Example&  ex) {} //拷贝构造函数,函数体为空
 8
 9       void test (Example param) {} //test成员函数
10
11  };

2、

 1 class Example {
 2
 3  public:
 4
 5       Example() {}
 6
 7       Example(const Example ex) {} //拷贝构造函数,函数体为空
 8
 9       void test (Example param) {} //test成员函数
10
11  };

可以看出:1与2的区别在于第7行的拷贝构造函数。事实上,在VS或GCC下,2中的Example类是无法编译通过的,会报错。原因就是其形参类型为非引用类型。

那么,2中第7行定义的拷贝构造函数在实际中会发生或导致什么问题呢?就是无穷递归。(PS:这里的递归与普通的递归还有些区别:普通的递归会有基准情形,即递归可以终止。而这里的递归无基准情形,则会无穷递归下去)

为了清楚的说明这个问题,我们假设2中的代码能够通过编译,进行如下测试,看看会发生什么:

3、

 1 int main ()  {
 2
 3    Example  obj;  //定义一个Example类的对象obj
 4
 5    test(obj);   //调用test成员函数
 6
 7    return 0;
 8
 9
10 }

3中的第3行定义了一个Example类的对象,然后调用test函数。

即test(obj);   因为test的形参为值传递方式

test的原型为:

void test (Example param) ;

所以在执行函数体之前,会发生实参到形参的拷贝,

即  Example param(obj);

Example param(obj)这一步,其本身也是一个函数,只不过它是特殊的拷贝构造函数而已,其原型为 Example(const Example ex) ;
那么按照2代码中对Example类的定义,其拷贝构造函数的形参是传值方式传递的,所以会发生实参到形参的拷贝,即 Example ex(obj);obj到ex的拷贝接着还会调用拷贝构造函数,为了方便说明,这一次的拷贝构造函数原型为: Example(const Example ex1) ;
则会发生:Example ex1(obj);obj到ex1的拷贝
同理,如此下去,还会有
Example ex2(obj),

Example ex3(obj),

.......,

Example exn(obj),

...........
子子孙孙无穷匮也。

最终会导致栈溢出(stackoverflow)。。。。程序崩溃。。。。
时间: 2024-10-07 18:15:33

关于 C++ 拷贝构造函数(copy constructor)中的形参必须为引用类型的详解的相关文章

(C++)关于拷贝构造函数 Copy Constructor

题目: In which of the following scenarios is a Copy Constructor called or invoked? A.    When no conversion function exists for converting the class object to another class object B.    When an existing object is assigned an object of its own class C. 

HTML中javascript的<script>标签使用方法详解

原文地址:HTML中javascript的<script>标签使用方法详解 只要一提到把JavaScript放到网页中,就不得不涉及Web的核心语言--HTML.在当初开发javascript的时候,Netscape要解决的一个重要问题就是如何做到让JavaScript既能与HTML页面共存,又不影响那些页面在其他浏览器中的呈现效果.经过尝试.纠错和争论,最终的决定就是为Web增加统一的脚本支持.而Web诞生早期的很多做法也都保留了下来,并被正式纳入HTML规范当中. <script&g

day01_linux中与Oracle有关的内核参数详解

linux中与Oracle有关的内核参数详解 在安装Oracle的时候需要调整linux的内核参数,但是各参数代表什么含义呢,下面做详细解析. Linux安装文档中给出的最小值: fs.aio-max-nr = 1048576 fs.file-max = 6815744 kernel.shmall = 2097152 kernel.shmmax = 4294967295 kernel.shmmni = 4096 kernel.sem = 250 32000 100 128 net.ipv4.ip

CSS中伪类及伪元素用法详解

原文:CSS中伪类及伪元素用法详解 伪类的分类及作用: 注:该表引自W3School教程 伪元素的分类及作用: 接下来让博主通过一些生动的实例(之前的作业或小作品)来说明几种常用伪类的用法和效果,其他的读者可以自己尝试: :active  大致效果为用鼠标点击时,元素增加特效,鼠标松开时,特效消失.多用在按钮的点击上. 写法: 这里id为box的是一div块,在css中首先设置了他的基本样式,下面为加入:active伪类后需要修改的样式. 未点击时: 点击之后: :active.:hover.:

【转载】3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解

原文:3D/2D中的D3DXMatrixPerspectiveFovLH和D3DXMatrixOrthoLH投影函数详解 3D中z值会影响屏幕坐标系到世界坐标系之间的转换,2D中Z值不会产生影响(而只是屏幕宽高比会产生影响,z值只对深度剔除产生影响).所以U3D中如果用2D摄像机那么屏幕坐标和世界坐标之间的转换需要用指定的2D摄像机才行,如果用主3D摄像机那么UI转换会产生计算结果异常. 一.D3DXMatrixPerspectiveFovLH函数 作用:Builds a left-handed

oracle中的exists 和not exists 用法详解

oracle中的exists 和not exists 用法详解 有两个简单例子,以说明 “exists”和“in”的效率问题 1) select * from T1 where exists(select 1 from T2 where T1.a=T2.a) ; T1数据量小而T2数据量非常大时,T1<<T2 时,1) 的查询效率高. 2) select * from T1 where T1.a in (select T2.a from T2) ; T1数据量非常大而T2数据量小时,T1>

iOS中touches事件,addtarget ...action和GestureRecognizer详解

刚学完uiview,uicontrol类,许多人知道 touchesBegain,touchesMoved,touchesEnd,GestureRecognizer的用途,但仔细考虑这些事件之间的关系,却令人头疼. 现在以一个例子来分析它们的内部实现: - (void)viewDidLoad { UIButton * btn=[[UIButton alloc]initWithFrame:CGRectMake(20, 40, 50, 50)]; [self.view addSubview:btn]

P?H?P?中?h?t?t?p?协?议?详?解

对PHP文件来说 Php可以有  html   css javascript php脚本 flash它的不同部分是在不同的地方执行的(服务器和客户端) http协议 1. http协议是建立在 tcp/ip协议基础上 2. 我们的web开发数据的传输都是依赖于http协议 3. http协议全称是超文本传输协议 http协议的  http请求 基本结构: 请求行 消息头 消息体(实体内容) Accept  text/html,application/xhtml+xml,application/x

spring中quatz的多定时任务配置图文详解

近来公司让用quatz框架做定时功能,而且还是执行多定时任务,真是苦恼. 虽然从网上搜了很多资料,但是写法上不太尽如人意,最后还是请教了螃蟹大神,给的配置建议就是简单啊,现在拿来分享下: 这里我们需要的有两部分,一个是java中的处理类,一个是quatz的配置文件,截图如下applicationContext_quartz.xmlquatz的配置文件地址地址:http://www.itxxz.com/a/kuangjia/kuangjiashili/2014/0602/10.html java中