Fork me on GitHub

C++——Big Three(copy ctor、copy op=、dtor)

Big Three

C++ 中Big Three指的是copy ctor 和 copy op=  和  dtor

m_data是个字符串指针。一般而言,处理字符串,都是使用指针,在需要存储字符的时候再创建内存,这是因为字符串的长度有大有小,指针的处理方式有种动态的感觉。使用数组的话,则无法准确设置字符串大小。

默认情况下,如果不写Big Three的话,compiler会帮助我们构造一个。对于copy ctor 、copy op= 其默认行为是逐bit去copy。对于dtor,其默认行为是private data逐bit删除。既然compiler针对Big Three已经提供了一套实现,我们还有必要去写吗?回答这个问题,我们先要弄清楚compiler默认给出的Big Three够不够用。对于Class without pointer member(s),往往compiler默认提供的那套Big Three就够了。但是对于Class with pointer member(s),使用compiler默认提供的那套Big Three往往会导致memory leaks

构造函数:ctor

字符串是什么,从C语言延续下来的概念:有个指针指向一个头,然后后面跟着一串,最后是'\0'结束符号。一个字符串多长,有2种想法

一种是,我不知道多长,但是最后有'\0'结束符号。

另外一种是,最后没有'\0'结束符号,但是有一个表示长度的整数。

拷贝构造函数:copy ctor

接受的是他自己这种东西

拷贝赋值函数:copy op=

接受的是他自己这种东西

compiler默认行为

compiler默认提供的copy ctor,其逐bit拷贝行为如下

默认行为带来两个问题:

①b=a后,b原本指向的memory就发生了内存泄漏。

②b和a指向一块memory,一个改动memory另一个也会跟着受影响。

copy op=的正确步骤一般是是:

①检查self copy

②taiget端原有数据清空

③target端分配和source端相同大小memory

④把source端内存copy到target端

为什么一定要检查self-copy

有两点原因

①浅层原因:都已经存在一份object了,自己拷贝自己还要执行上面copy op=的②~④,效率低下

②本质原因:问题的根本原因并不是效率上的损失那么简单。这可能导致程序行为的不确定性。

如果没有self copy检查,开始copy op=时如下

执行完②,在执行③时,计算source所占memory时行为是不确定的,即neimory具体大小是不确定的。导致后面为target分配内存行为也不确定。最终会导致程序执行情况的不确定。

析构函数:dtor

这段代码展示了ctor和dtor的用法。s1、s2是开辟function stack memory,系统可以自动回收。p开辟的是system heap memory,需要Programmer手动回收。在离开{ }时s1、s2会自动自动调用dtor回收memory。delete p的时候也会调用dtor回收memory。因此整段代码调用3次ctor,3次dtor。

程序执行析构函数的时机有以下4种。

  • 如果在函数中定义了一个对象,当这个函数调用结束时,对象会被释放,且在对象释放前会自动执行析构函数。
  • static局部对象在函数调用结束时对象不释放,所以也不执行析构函数,只有在main 函数结束或调用exit函数结束程序时,才调用static局部对象的析构函数。
  • 全局对象则是在程序流程离开其作用域(如main 函数结束或调用exit函数)时,才会执行该全局对象的析构函数。
  • 用new建立的对象,用delete释放该对象时,会调用该对象的析构函数。析构函数的作用不是删除对象,而是在撤销对象占用的内存前完成一些清理工作,使得放些内存可以供新对象使用。析构函数的作用也不限于释放资源方面,它还可以被用来执行用户希望在最后一次使用对象之后所执行的任何操作。

 

 

posted @ 2018-08-06 12:44  克拉默与矩阵  阅读(1210)  评论(0编辑  收藏  举报