一、认识析构函数

在我的前一篇博客介绍了类的构造函数。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. Gdb 常用命令

    命令名称 含义 示例 b  fun_name 设置断点 b  main b 行号 if  条件 设置带条件断点 如:b 11 if  i==10 n 下一行 n s 跳入函数内部 s  sum fin ...

  2. IO_REMOVE_LOCK使用方法小结(转载加改正)

    原文链接:http://www.programlife.net/io_remove_lock.html IO_REMOVE_LOCK(删除锁)的具体结构没有公开,WDK的文档中中查不到IO_REMOV ...

  3. bzoj 1095 [ZJOI2007]Hide 捉迷藏(括号序列+线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=1095 [题意] 给定一棵树,树上颜色或白或黑而且可以更改,多个询问求最远黑点之间的距离 ...

  4. DIY 博客全文界面的推荐、反对、加关注、返回顶部、快速评论等小功能的集成

    博客园已经很不错了,但作为比较“挑剔”的用户,在使用的过程中,还是有一些地方不爽的. 我不是一个专业的前台程序员,也只能凭借自己蹩脚的JS和CSS知识完成对页面的小改造(专业的大虾莫要鄙视呀..). ...

  5. ERROR: transport error 202: bind failed: Address already in use

    早上上班,同事反应服务上不去,后台看了一下,发现tomcat挂掉了,重新启动tomcat时报错. ERROR: transport error 202: bind failed: Address al ...

  6. android开发中遇到的问题

    7.ExpandableListView setOnChildClickListener无效,请在adapter的方法isChildSelectable返回true即可 6.使用<shape/& ...

  7. A Tour of Go Switch evaluation order

    Switch cases evaluate cases from top to bottom, stopping when a case succeeds. (For example, switch ...

  8. php 接收 Content-Type 是 application/json的请求数据

    工作中为其他公司编写了一个提供请求的接口,自己调试的时候是用form提交的,所以可以用$_POST取键接收方式,而对接联调的时候发现总是取不到数据,把$_POST整个序列化放入日志也是[] ,空的,于 ...

  9. 【C++深入浅出】设计模式学习之观察者模式

    前言 前两天学习了weak_ptr以后还是不甚明了,一则需要实际应用去锤炼,二来就是不懂观察者模式. 正文 观察者模式又叫发布-订阅模式,定义了一种一对多的依赖关系,让多个观察者对象同时监听某一主题对 ...

  10. 在与SQL Server建立连接时出现与网络相关的或特定于实例的错误

    向往前一样.学习牛腩新闻公布系统的视频,写程序,打开数据库.出现一个框框,具体内容例如以下: 数据库连接不上.全部的工作都要歇班,捣鼓了会儿,简单总结一下解决该问题的方法. 首先:第一步,程序--SQ ...