打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
[c 03]为啥需要拷贝构造?

前言

今天咱们主要来探究一下,我们为啥需要拷贝构造这个东西,以及拷贝构造的一些基本语法。

正文

在这里呢,我先给一段测试程序,探究一下没有拷贝构造对于类到底会有什么影响。

这段程序我也是参考了浙江大学的翁恺老师教授C++课程时上课的例程,感谢翁恺老师的无私奉献!

这段程序看起来比较复杂,让我来慢慢分析一下。首先我定义了一个static的变量i,为什么要是static的呢?因为我需要i是全文件可见的。

然后我构造了一个A类,在A类的构造函数里面,我将全局的i进行自加1,并且输出一些相关信息,在A类的析构函数里面,我将全局的i进行自减1,并且输出一些相关信息。

为什么要这么做呢,其实就是为了记录A类生成对象的时候,构造函数和析构函数被调用的情况。

那么在A类里面还有print_i()这个函数,也就是为了打印调用函数时刻的i值。

那么在这个测试程序里面发生了几次对象的实例化呢?

仔细数数一共是3次,a, a2和f()函数的形参a_t,当调用f()函数的时候,f()函数会根据实参a来构造出一个形参a_t来。

那么我们来看看程序的结果输出是什么:

正常来说,当最后程序结束的时候,i的数值应该是0,但是结果确实-2,说明此时程序肯定是有了问题的。

为了说明这个问题,我需要一些先备知识,那就是关于c++的=号的,在c++里面将对象a赋给b,也就是做对象的a=b的时候,这个=时如何起作用呢?

那就需要知道c++里面的运算符重载相关知识了,c++里面的运算符是可以重载成用户需要的功能的,也就是说=实现的功能可以是将两边的变量或者常量进行相减(当然,我非常不建议这样做)。

好了,言归正传,在这个测试程序里,我们并没有重载=号,所以如果用了=号的时候,程序应用的就是默认的=功能。

那么如何进行对象的默认赋值呢?也就是说对象的a=b到底发生了什么呢?

其实这个发生的就是拷贝工作,不过这个拷贝不是按字节进行拷贝的,而是按照成员进行拷贝的,不是bitwise的拷贝,而是memberwise的拷贝。

所以对象的a=b的时候,是将对象b里面放的成员变量按照成员拷贝到对象a里面的。

好了,回到了我们的测试程序,首先我们构造出了a这个对象,此时i=1,这没有问题,接下来我调用了f(),此时就发生了一次对象的拷贝,因为将实参对象a拷贝成了形参a_t,发生了memberwise的拷贝。

但是此时i没有进行自加,这说明构造函数没有被调用,这就很奇怪了,导致函数结束的时候调用了对象的析构函数,i进行了自减,导致i变成了0。

接下来A a2=f(a);又发生了一次memberwise的拷贝,此时构造函数又没有被调用,因为此时的i是0。最后,a和a2都被析构了,导致i进行了2次自减操作从而变成了-2。

经过我们分析,问题就很明白了,当对象发生memberwise的拷贝的时候并不会调用默认构造函数,也就是default constructor,这是很危险的,一个对象做出来的时候没有被初始化过是非常危险的,因此我们要解决它,解决方式就是拷贝构造函数。

拷贝构造函数的作用就是用已有的对象来初始化一个新的同类对象,也就是说做对象的a=b的时候,拷贝构造函数是会被调用的。

可以理解成将对象b做为参数来实例化类A得到对象a,看下面这段例程感受一下:

结果如下:

可以看到i最后变成了0,说明拷贝构造函数起作用了。

所以,为了保证程序的正常运行,以后写类的时候,记得要写一个拷贝构造函数。



《如何基于视觉深度强化学习实现机械臂抓取 · 文岩》

      适用于对强化学习和机器人学有一定基础的同学,对强化学习的基本概念、基础理论有了解,对机械臂的正逆运动学有了解,熟悉Python编程,了解PyTorch。

(扫描二维码查看课程详情)

点击“阅读全文”即可加入学习


本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
两个比较容易混淆的概念:Default Memberwise Initialization和Bitwise Copy
C /C入门之拷贝构造函数
C/C++常见面试题[转帖]
与LSGO一起学“9 引用(9.10 用值来传递对象)”
算法岗常问的一些C 基础知识
浅谈C++对象的拷贝与赋值操作
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服