前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >类的构造函数和析构函数

类的构造函数和析构函数

作者头像
用户5521279
发布2019-06-02 17:17:02
1.7K0
发布2019-06-02 17:17:02
举报
文章被收录于专栏:搜狗测试搜狗测试

一、构造函数和析构函数的由来

类的数据成员不能在类的声明时候初始化,为了解决这个问题? 使用构造函数处理对对象的初始化。构造函数是一种特殊的成员函数,与其他函数不同,不需要用户调用它,而是创建对象的时候自动调用。析构函数是对象不再使用的时候,需要清理资源的时候调用。

二、类的构造函数

(1)初识类的初始化

C++支持两种初始化形式:复制初始化和直接初始化,对于类直接初始化直接调用实参匹配的构造函数,复制初始化总是调用复制构造函数。

(2)类的初始化和构造函数的关系

常用的类的初始化方式大概有以下5种:

ClassTest ct1("ab");

ClassTest ct2 = "ab";

ClassTest ct3 = ct1;

ClassTest ct4(ct1);

ClassTest ct5 = ClassTest();

那么以上五种方式类的初始化,又是什么初始化呢,以及调用了哪些构造函数呢?上代码:

上述代码中,将复制构造函数delete了,所以初始化需要调用复制构造函数就会报错,因此我们验证有哪些初始化报错了即可。下面是编译器中报错提示。大概意思就是复制构造函数被删除了。结果显示只有第一种初始化方式不需要调用复制构造函数。

因此可以得出结论:

ClassTest ct1("ab"); //直接初始化

ClassTest ct2 = "ab"; //复制初始化

ClassTest ct3 = ct1; //复制初始化

ClassTest ct4(ct1); //复制初始化

ClassTest ct5 = ClassTest(); //复制初始化

这里面有必要解释下“=”,类的初始化过程中的“=”,是隐式调用复制构造函数,而不是调用赋值运算符函数。

当用于类类型对象时,初始化的复制形式和直接形式有所不同:直接初始化直接调用与实参匹配的构造函数,复制初始化总是调用复制构造函数。复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象

从上面的经典说法中,我们也可以知道,直接初始化不一定要调用复制构造函数,而复制初始化一定要调用复制构造函数。实际是不是这样呢,请看下面代码。

结果输入为:

看样子结果有些矛盾,复制初始化一定要调用复制构造函数,但是执行发现并没有调用,反而却和直接初始化调用方式一样。但是把复制构造函数删除却还报错

(3)矛盾结果产生的原因

产生上面的运行结果的主要原因在于编译器的优化,而为什么把复制构造函数声明为delete,就能把这个假象去掉呢?主要是因为复制构造函数是可以由编译默认合成的,而且是公有的(public),编译器就是根据这个特性来对代码进行优化的。然而如里你自己定义这个复制构造函数,编译则不会自动生成,虽然编译不会自动生成,但是如果你自己定义的复制构造函数仍是公有的话,编译还是会为你做同样的优化。然而当它是delete时,编译器就会有很不同的举动,因为你明确地告诉了编译器,你明确地拒绝了对象之间的复制操作,所以它也就不会帮你做之前所做的优化,你的代码的本来面目就出来了。

三、类的析构函数

类的析构函数和构造函数作用相反,释放对象使用的资源,并销毁非static成员。

(1)内存泄漏

下面代码有何隐患?

回想我们在函数体内定义一个非static的变量,那么在函数执行之后变量就会被销毁,那么如果我们指向了动态开辟的一块空间的指针,我们需要手动free掉,否则就会出现内存泄漏。

其实类也是一样的,上述代码就会有内存泄漏的风险。如何解决呢?看下述代码。

在上述代码中,我们在析构函数中,添加delete函数。解决了内存泄漏的问题,但是还存在其他问题。

(2)多次释放资源

上代码:

在上述代码中,用ct初始化了ct1。由于默认复制构造函数都是浅拷贝,所以对象ct中的p和对象ct1中的p都是指向同一块内存空间。在mian函数执行完毕之后,ct和ct1分别调用析构函数,所以delete两次同一块内存空间,所以程序会崩溃。下面的输出结果也验证了我们的猜想是正确的。建议在这种情况下采用深拷贝进行操作。

四、总结

1、类的复制初始化无优化的调用方式,复制初始化首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。

2、对于类的复制初始化的构造函数的调用方式,编译器已经将其作为普遍方法而不是作为一种优化。

3、类的初始化过程中的“=”,是隐式调用复制构造函数,而不是调用赋值运算符函数。

4、当析构函数中存在手动释放资源的时侯,一定要注意之前是否释放过,以及以后是否有其他操作会释放。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-05-14,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 搜狗测试 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档