一、认识析构函数

在我的前一篇博客介绍了类的构造函数。http://www.cnblogs.com/MrListening/p/5557114.html。

这里我们来简单说说类的析构函数,它是类的一个成员函数,名字由波浪号加类名构成。看它的名字我们大概就能联想到他功能,是执行与构造函数相反的操作:释放对象使用的资源,并销毁非static成员。

同样的,我们来看看析构函数的几个特点:

1.函数名是在类名前加上~,无参数且无返回值。

2.一个类只能有且有一个析构函数,如果没有显式的定义,系统会生成一个缺省的析构函数(合成析构函数)。

3.析构函数不能重载。每有一次构造函数的调用就会有一次析构函数的调用。

拿程序说话:

//by Mr_Listening,06 08 2016
class Date
{
public:
Date(int year=,int month=,int day=)
: _month(year), _year(month), _day(day)
{ }
~Date()
{
cout << "~Date()" << this << endl;
}
private:
int _year=;
int _month;
int _day;
};
void test()
{
Date d1;
}
int main()
{
test();
return ;
}

在test()函数中构造了对象d1,那么在出test()作用域d1应该被销毁,此时将调用析构函数,下面是程序的输出。当然在构建对象时是先调用构造函数的,在这里就不加以说明了。

我们知道,在构造函数中,成员的在初始化是在函数体执行前完成的,并按照成员在类中出现的顺序进行初始化,而在析构函数中,首先执行函数体,然后再销毁成员,并且成员按照初始化的逆序进行销毁。

二、销毁,清理?

我们一直在说析构函数的作用是在你的类对象离开作用域后释放对象使用的资源,并销毁成员。那么到底这里所说的销毁到底是什么?那么继续往下看:

void test ()

{

int a=10;

int b=20;

}

回想我们在一个函数体内定义一个变量的情况,在test函数中定义了a和b两个变量,那么在出这个函数之后,a和b就会被销毁(栈上的操作)。那么如果是是一个指向动态开辟的一块空间的指针,我们都知道需要自己进行free,否则会造成内存泄漏。

说到这里,其实在类里面的情况和这是一样的,这就是合成析构函数体为空的原因,函数并不需要做什么,当类对象出作用域时系统会释放你的内置类型的那些成员。但是像上面说的一样,如果,我的成员里有一个指针变量并且指向了一块你动态开辟的内存,那么像以前那样也需要自己来释放,此时就需要在析构函数内部写你的释放代码,这样在调用析构函数的时候就可以把你所有的资源进行释放。(其实这才是析构函数有用的地方,对吗)

那么还有一点,当类类型对象的成员还有一个类类型对象,那么在析构函数里也会调用这个对象的析构函数。

三、析构函数来阻止该类型对象被销毁?

我们如果不想要析构函数来对对象进行释放该怎么做呢,不显式的定义显然是不行的,因为编译器会生成默认的合成析构函数。之前我们知道了如果想让系统默认生成自己的构造函数可以利用default,那么其实还有一个东西叫做delete。

class Date
{
public:
Date(int year=1990,int month=1,int day=1)
: _year(year),_month(month), _day(day)
{ }
~Date() = delete; private:
int _year=1990;
int _month;
int _day;
};

     如果我这么写了,又在底下创建Date类型的对象,那么这个对象将是无法被销毁的,其实编译器并不允许这么做,直接会给我们报错。

但其实是允许我们动态创建这个类类型对象的,像这样:Date* p = new Date;虽然这样是可行的,但当你delete p的时候依然会出错,原因就不用说了吧

所以既然这样做的话既不能定义一个对象也不能释放动态分配的对象,所以还是不要这么用为好喽。

四、注意喽

一般在你显式的定义了析构函数的情况下,应该也把拷贝构造函数和赋值操作显式的定义。为什么呢??

看下面的改动:

class Date
{
public:
Date(int year=1990,int month=1,int day=1)
: _year(year),_month(month), _day(day)
{
p = new int;
}
~Date()
{
delete p;
} private:
int _year=1990;
int _month;
int _day;
int *p;
};

  成员中有动态开辟的指针成员,在析构函数中对它进行了delete,如果不显式的定义拷贝构造函数,当你这样:Date d2(d1)来创建d2,我们都知道默认的拷贝构造函数是浅拷贝,那么这么做的结果就会是d2的成员p和d1的p是指向同一块空间的,呢么调用析构函数的时候回导致用一块空间被释放两次,程序会崩溃的哦!

最后,

我们知道析构函数是可以调用的,那么构造函数可不可以呢?是怎样的使用环境

C++之类的析构函数的更多相关文章

  1. .NET 基础 一步步 一幕幕[面向对象之构造函数、析构函数]

    构造函数.析构函数 构造函数: 语法: //无参的构造函数 [访问修饰符] 函数名() :函数名必须与类名相同. //有参的构造函数 [访问修饰符] 函数名(参数列表):函数名必须与类名相同. 作用: ...

  2. 【C#】析构函数

    MSDN paper 析构函数 析构函数(destructor) 与构造函数相反,当对象脱离其作用域时(例如对象所在的函数已调用完毕),系统自动执行析构函数. 析构函数往往用来做“清理善后” 的工作( ...

  3. c++虚析构函数

    虚析构函数的作用主要是当通过基类指针删除派生类对象时,调用派生类的析构函数(如果没有将不会调用派生类析构函数) #include <iostream> using namespace st ...

  4. 转:Delphi2010新发现-类的构造和析构函数功能

    Delphi2010发布了. 虽然凭着对Delphi的热爱第一时间就安装了,但是现在可能是年纪大了,对新事物缺乏兴趣了.一直都没有仔细研究. 今天有点时间试了一下新功能. 本来C#和Delphi.NE ...

  5. c++单例模式为什么不在析构函数中释放静态的单例对象(转)

    需要清楚一下几点:   1.单例中的 new 的对象需要delete释放.   2.delete释放对象的时候才会调用对象的析构函数.   3.如果在析构函数里调用delete,那么程序结束时,根本进 ...

  6. C++构造函数/析构函数 设置成private的原因

    C++构造函数/析构函数 设置成private的原因 标签(空格分隔): c/c++ 将构造函数,析构函数声明为私有和保护的,那么对象如何创建? 已经不能从外部调用构造函数了,但是对象必须被构造,应该 ...

  7. 关于GC和析构函数的一个趣题

    这个有趣的问题感谢装配脑袋友情提供. 请看如下代码: public class Dummy { public static Dummy Instance; ; ~Dummy() { Instance ...

  8. C++构造函数和析构函数

    构造函数简介 在上一个章节我们在创建好类的对象之后,首先对它的每一个成员属性赋值之后再对它们进行输出操作,如果不赋值就输出,这些值就会是垃圾值.而为了代码的简介,一次性为所有成员属性初始化,C++的类 ...

  9. virtual 修饰符与继承对析构函数的影响(C++)

    以前,知道了虚函数表的低效性之后,一直尽量避免使用之.所以,在最近的工程中,所有的析构函数都不是虚函数.今天趁着还书的机会到图书馆,还书之后在 TP 分类下闲逛,偶然读到一本游戏编程书,里面说建议将存 ...

  10. 谈一谈.net析构函数对垃圾回收的影响

    之前忘了说了 代码都是在Release模式下运行的,现在补充上. 这里说析构函数,其实并不准确,应该叫Finalize函数,Finalize函数形式上和c++的析构函数很像 ,都是(~ClassNam ...

随机推荐

  1. 黑盒测试用例设计方法&理论结合实际 -> 场景法

    一概念 现在的软件几乎都是用事件触发来控制流程的,事件触发时的情景便形成了场景,而同一事件不同的触发顺序和处理结果就形成事件流.这种在软件设计方面的思想也可以引入到软件测试中,可以比较生动地描绘出事件 ...

  2. java中equals和==的区别 (转)

    java中equals和==的区别  值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存储引用类型变量的地址,而其本身则存储在堆中. ==操作比较的是两个变量的值是否相等,对于引 ...

  3. PHP 实现短域名互转

    /** * 短域名生成&解析类 */ class Build_URL { private $mem; private $base_url = 'http://xxx.com/'; public ...

  4. C#操作Json(转)

    原文:http://wenku.baidu.com/link?url=3dlqKdF26ZdQIAcX9jvP2ZYEtl3J0sKOV8XuHQI0Rz4SjB9S46nqmGiMXUVQa_1Pm ...

  5. Sort--快速排序

    快速排序 1 public class QuickSort{ 2 3 public static int Partition(int[] a,int low,int high){ 4 int pivo ...

  6. yum cdh4

    cdh4 install for Centos6那个最美的年代,最好的时光,一路梦想,一路流泪,流的不会是懦弱的泪,而是对奋斗的寄于;1,repo配置>>>/etc/yum.repo ...

  7. 教程-经典Delphi教程网

    有理想+志同道合的人+取长补短去协同工作=完美团队一流的项目 + 三流的执行者 = 垃圾项目三流的项目 + 一流的执行者 = 完美项目 自己公司网址:http://www.kaideruixin.ic ...

  8. [iOS基础控件 - 5.3] 电台APP可滚动主界面(UIScrollView制作)

    A.功能 1.上下可滚动的电台 2 x n 的图标集 2.顶部半透明标题 3.底部半透明功能按钮   B.实现思路 1.设置图标.启动画面       2.拖入UIScrollView,设置背景色 ( ...

  9. Qt 固定窗口【worldsing 笔记】

    w.setWindowFlags(Qt::WindowMinimizeButtonHint); //禁止最大化按钮 w.setFixedSize(1024,587);//固定窗口大小

  10. 基于XML数据库的学生信息管理系统的设计与实现

    本项目是在学习之余写的,主要用来练习MVC+DAO的分层设计思想,项目基于一个简单的XML学生数据库,使用XML作为数据库的原因是其十分的小巧与方便,使用dom4j即可进行方便的解析.因为这段时间课程 ...