当前位置:网站首页 > 技术博客 > 正文

构造函数和拷贝构造函数



本文收录于微信公众号「 LinuxOK 」,ID为:Linux_ok,关注公众号第一时间获取更多技术学习文章。

1. c++类的默认拷贝构造函数的弊端
c++类的中有两个特殊的构造函数,(1)无参构造函数,(2)拷贝构造函数。它们的特殊之处在于:
(1)当类中没有定义任何构造函数时,编译器会默认提供一个无参构造函数且其函数体为空;
(2)当类中没有定义拷贝构造函数时,编译器会默认提供一个拷贝构造函数,进行成员变量之间的拷贝。(这个拷贝操作是浅拷贝)


这里只讲拷贝构造函数。在c语言中,

 
  

上面的初始化及赋值操作是最正常不过的语法,c++语言肩挑兼容c语言语法的责任,所以在类的设计上,也兼容这种操作:

 
  

如上的初始化类需要调用到cls类的默认实现的拷贝构造函数,为类赋值需要调用的是cls类的默认实现的赋值操作符重载函数,它们都是浅度拷贝的。前者其原型为:

 
  

默认的拷贝构造函数存在弊端,看如下类定义:

 
  

类中的指针p在构造函数中分配的空间,在析构函数中释放。

 
  

编译运行确实不会出错:
这里写图片描述

类在我们没有定义拷贝构造函数的时候,会默认定义默认拷贝构造函数,也就是说可以直接用同类型的类间可以相互赋值、初始化:

 
  

编译通过,运行却出错了:
这里写图片描述

原因就在于,默认的拷贝构造函数实现的是浅拷贝。

2. 深度拷贝和浅拷贝
深度拷贝和浅拷贝在c语言中就经常遇到的了,在这里我简单描述。
一般的赋值操作是深度拷贝:

 
  

简单的指针指向,则是浅拷贝:

 
  
 
  

将上面的浅拷贝改为深度拷贝后:

 
  
 
  

稍微有点c语言基础的人都能看得出深度拷贝和浅拷贝的差异。总而言之,拷贝者和被拷贝者若是同一个地址,则为浅拷贝,反之为深拷贝。
以字符串拷贝为例,浅拷贝后,str1和str2同指向0x,不管哪一个指针,对该空间内容的修改都会影响另一个指针。
这里写图片描述

深拷贝后,str1和str2指向不同的内存空间,各自的空间的内容一样。因为空间不同,所以不管哪一个指针,对该空间内容的修改都不会影响另一个指针。
这里写图片描述

 
  

main函数将要退出时,拷贝类t2的析构函数先得到执行,它把自身p指向的堆空间释放了;接下来,t1的析构函数得到调用,被拷贝类t1的析构函数得到调用,它同样要去析构自身的p指向指向的堆空间,但是该空间和t2类中p指向的空间一样,造成重复释放,程序运行崩溃。

解决办法十分简单,自定义拷贝构造函数,里面用深度拷贝的方式为拷贝类初始化:

 
  

编译运行正常:
这里写图片描述

关于c++拷贝构造函数的深度拷贝和浅拷贝的介绍到这里,其实还可以将它们的地址打印出来看看,不过这一步就不再赘述了。

c++的拷贝构造函数还有一处妙用,就是自定义拷贝构造函数,并设置为private属性,其实现体可以什么都不写,那么这个类将变成一个不可被复制的类了。

版权声明


相关文章:

  • 计算机系统组成及其工作原理2025-09-30 12:30:01
  • android 设置textview内容2025-09-30 12:30:01
  • clr错误8007000e怎么办2025-09-30 12:30:01
  • 面向对象编程c++程序2025-09-30 12:30:01
  • 逻辑回归操作步骤2025-09-30 12:30:01
  • 什么是java并发编程2025-09-30 12:30:01
  • 消防安全的四懂四会和四个能力分别是什么2025-09-30 12:30:01
  • 计算机组成包括哪些2025-09-30 12:30:01
  • 算法个性化推荐解释2025-09-30 12:30:01
  • html导入外部js文件代码2025-09-30 12:30:01