c++关于c++类的析构函数数的问题

C++ 类构造函数和析构函数_Linux编程_Linux公社-Linux系统门户网站
你好,游客
C++ 类构造函数和析构函数
来源:Linux社区&
作者:gaopengtttt
C++ 类构造函数和析构函数1、构造函数:构造函数用于对对象的数据进行初始化,构造函数的和一般的方法(函数)有一些不同& & & & & & &他的名字必须是类的名字,不能带返回值。一般来说即使你不建立构造函数,也会& & & & & & &为你建立默认的构造函数,但是默认的构造函数是什么都不干的。如:& & & & & & &stu::stu(void){}2、析构函数:析构函数用于对对象的内存进行回收,(如用malloc和new分配的内存空间)析构函数在& & & & & & &对象消亡的时候会被自动调用,而不需要你手动调用,名称为类名字前面加上~。一样& & & & & & &析构函数不能带返回值,并且析构函数没有参数,同样如果你设置析构函数,也会& & & & & & &为你默认建立析构函数,但是默认也是什么都不做的。另外需要注意的是:1、构造函数可以有3种调用方法--stu yl(1,"yanlei") 隐含调用,并且赋值-- & & & & & &隐含调用,可能函数重载了--stu yl = stu(1,"yanlei") 显示调用,并且赋值注意调用stu yl(void)是不可以的这是一个返回stu类的函数原型(C++11引入了其他的初始化方式这里不讨论)2、构造函数,不能带返回值。析构函数,不能带参数和返回值3、对象初始化后可以使用构造函数重新赋值如下:& &stu yl = stu(1,"yanlei");& &yl = stu(1,"gaopeng");& &但是此时使用的方法是建立一块临时空间,然后复制对象数据到对象,然后& &释放,所以需要调用一次析构函数。4、构造函数他的名字必须是类的名字,析构函数类名字前面加上~ 如:& &stu::stu(void);& &stu::~stu(void);来看一段代码:
::::::::::::::
::::::::::::::
/*************************************************************************
& & & File Name: ct1.h
& & & Author: gaopeng
& & & Mail: gaopp_.com
& & & Created Time: Mon 13 Jun 2016 01:54:32 AM CST
&************************************************************************/
#include&iostream&
using namespace std;
typedef struct mem
& & & & int t_sorce_;
& & & & const char *name_;
& & & & private:
& & & & & & & & int id_;
& & & & & & & & MEM st_;
& & public:
& & & & & & & & &stu(int id,const char *name);//构造函数
& & & & & & & & &stu(void);//构造函数
& & & & & & & & int set_src(int id,int a,int b,const char *name);
& & & & & & & & int sh_src(void);
& & & & & & & & const stu* check(const stu* info) const;
& & & & & & & & &~stu(void); //析构函数
::::::::::::::
::::::::::::::
/*************************************************************************
& & File Name: fu.cpp
& & Author: gaopeng
& & Mail: gaopp_.com
& & Created Time: Mon 13 Jun 2016 02:02:26 AM CST
&************************************************************************/
#include&iostream&
#include "ct1.h"
using namespace std;
//构造函数使用函数重载
stu::stu(int id,const char *name) //构造函数,不能带返回值
& & & & id_ = id;
& & & & st_.name_ = name;
& & & & st_.t_sorce_ = 0;
stu::stu(void) //构造函数,不能带返回值
& & & & static char name[20] = "gaopeng";
& & & & st_.name_ = name;
& & & & id_ = 0;
& & & & st_.t_sorce_ = 0;
stu::~stu(void) //析构函数,不能带参数和返回值
& & & & cout && "call destructor for name:" && st_.name_ &&endl;
int stu::set_src(int id,int a,int b,const char *name)
& & & & id_ = id;
& & & & st_.t_sorce_ = a+b;
& & & & st_.name_ = name;
& & & & return 0;
int stu::sh_src(void)
& & & & cout && id_ &&endl;
& & & & cout && st_.t_sorce_ &&endl;
& & & & cout && st_.name_ &&endl;
& & & & return 0;
const stu* stu::check(const stu* info) const
& & & & if(info-&id_ & id_ )
& & & & & & & & return info;
& & & & else
& & & & & & & & return this; // this 指针
::::::::::::::
::::::::::::::
/*************************************************************************
& & & File Name: main.cpp
& & & Author: gaopeng
& & & Mail: gaopp_.com
& & & Created Time: Mon 13 Jun 2016 02:18:10 AM CST
&************************************************************************/
#include&iostream&
#include"ct1.h"
using namespace std;
int main(void)
& & & & char a[20] = "yanlei";
& & & & stu yl(1,a); //stu::stu(int id,const char *name),方法1进行初始化,显示初始化
& & & & yl.sh_src();
& & & & stu gp;// stu::stu(void) ,隐含初始化调用了重载函数stu()
& & & & gp.sh_src();
& & & & gp.set_src(2,10,20,"gaopeng1");
& & & & gp.sh_src();
& & & & stu gp2 = stu(3,"gaopeng2");//方法2进行初始化,方法2初始化可以有2个意思,意思1:初始化 意思2:如果已经初始化再次调用建立临时内容然后COPY到gp2的方式,并且释放临时
内存调用析构函数
& & & & gp2 = stu(3,"gaopeng3"); //再次重构类数据,通过建立临时内容然后COPY到gp2的方式,并且释放临时内存,所以调用了析构函数
& & & & gp2 = gp;
& & & & gp2.sh_src();
& & & & stu gp3;
& & & & cout && "gp3 resource:"&&endl;
& & gp3.sh_src();
& & & & gp3 = *(gp3.check(&gp2));
& & & & cout && "gp3 after check:"&&endl;
& & & & gp3.sh_src();
其中都有详细的解析,程序执行结果如下:10yanlei00gaopeng230gaopeng1call destructor for name:gaopeng3230gaopeng1gp3 resource:00gaopenggp3 after check:230gaopeng1call destructor for name:gaopeng1call destructor for name:gaopeng1call destructor for name:gaopeng1call destructor for name:yanlei注意call destructor for name:gaopeng3就是临时空间释放调用的析构函数并且注意this指针用法
本文永久更新链接地址:
相关资讯 & & &
& (09/09/:50)
& (07/14/:14)
& (08月27日)
& (07/17/:24)
& (03/24/:07)
   同意评论声明
   发表
尊重网上道德,遵守中华人民共和国的各项有关法律法规
承担一切因您的行为而直接或间接导致的民事或刑事法律责任
本站管理人员有权保留或删除其管辖留言中的任意内容
本站有权在网站内转载或引用您的评论
参与本评论即表明您已经阅读并接受上述条款关于c++显示调用析构函数的陷阱 - 蒲公英110 - 博客园
一、文章来由
现在在写一个项目,需要用到多叉树存储结构,但是在某个时候,我需要销毁这棵树,这意味着如果我新建了一个树对象,我很可能在某处希望将这个对象的声明周期终结,自然会想到显示调用析构函数,但是就扯出来这么大个陷阱。
在了解为什么不要轻易显示调用析构函数之前,先来看看预备知识。&为了理解这个问题,我们必须首先弄明白&堆&和&栈&的概念。
1)堆区(heap) && 一般由程序员分配释放, 若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。
2)栈区(stack) && 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
我们构造对象,往往都是在一段语句体中,比如函数,判断,循环,还有就直接被一对&{}&包含的语句体。这个对象在语句体中被创建,在语句体结束的时候被销毁。问题就在于,这样的对象在生命周期中是存在于栈上的。也就是说,如何管理,是系统完成而程序员不能控制的。所以,即使我们调用了析构,在对象生命周期结束后,系统仍然会再调用一次析构函数,将其在栈上销毁,实现真正的析构。
所以,如果我们在析构函数中有清除堆数据的语句,调用两次意味着第二次会试图清理已经被清理过了的,根本不再存在的数据!这是件会导致运行时错误的问题,并且在编译的时候不会告诉你!
三、显示调用带来的后果
如果硬要显示调用析构函数,不是不可以,但是会有如下3条后果:
1)显式调用的时候,析构函数相当于的一个普通的成员函数;
2)编译器隐式调用析构函数,如分配了对内存,显式调用析构的话引起重复释放堆内存的异常;
3)把一个对象看作占用了部分栈内存,占用了部分堆内存(如果申请了的话),这样便于理解这个问题,系统隐式调用析构函数的时候,会加入释放栈内存的动作(而堆内存则由用户手工的释放);用户显式调用析构函数的时候,只是单纯执行析构函数内的语句,不会释放栈内存,也不会摧毁对象。
用如下代码表示:
~aaa(){cout&&"deconstructor"&& }
这样的话,显式两次destructor,第一次析构相当于调用一个普通的成员函数,执行函数内语句,显示第二次析构是编译器隐式的调用,增加了释放栈内存的动作,这个类未申请堆内存,所以对象干净地摧毁了,显式+对象摧毁
aaa(){p = new char[1024];}
这样的话,第一次显式调用析构函数,相当于调用一个普通成员函数,执行函数语句,释放了堆内存,但是并未释放栈内存,对象还存在(但已残缺,存在不安全因素);第二次调用析构函数,再次释放堆内存(此时报异常),然后释放栈内存,对象销毁
四、奇葩的错误
系统在什么情况下不会自动调用析构函数呢?显然,如果对象被建立在堆上,系统就不会自动调用。一个常见的例子是new&delete组合。但是好在调用delete的时候,析构函数还是被自动调用了。很罕见的例外在于使用布局new的时候,在delete设置的缓存之前,需要显式调用的析构函数,这实在是很少见的情况。
我在栈上建树之后,显示调用析构函数,对象地址任然存在,甚至还可以往里面插入节点。。。
其实析构之前最好先看看堆上的数据是不是已经被释放过了。
所以,一般不要自作聪明的去显示调用析构函数。
随笔 - 145以下试题来自:
单项选择题下列有关析构函数的说法中,错误的是(
)。A.一个类中析构函数有且只有一个B.析构函数无任何函数类型C.析构函数和构造函数一样可以有形参D.析构函数的作用是在对象被撤销时收回先前分配的内存空间
为您推荐的考试题库
你可能感兴趣的试题
1A.2B.3C.4D.52A.记录B.字段C.文件D.数据库3A.必须是连续的B.部分地址必须是连续的C.一定是不连续的D.可连续可不连续4A.确认测试B.集成测试C.验证测试D.验收测试5A.int i=100;
i=i%100+1;
}B.int i,sum=0;
for(i=1;;i++)
sum=sum+1;C.int k=0;
}while(k>=0);D.int s=3379;
while(s++%2+3%2)
热门相关试卷
最新相关试卷关注51Testing
C++ 小心你的析构函数不会执行
发表于: 09:42 &作者:Step & 来源:51Testing软件测试网采编
推荐标签:
#include &string&#include &iostream&class Student{public:&&&&&&&&& Student(int num,string name)&&& {&&&&&&& this-&num=&&&&&&& this-&strname=&&& }&&& ~Student()&&& {&&&&&&& cout&&"num:"&&this-&num&&"name"&&this-&strname&&&&& }};int _tmain(int argc, _TCHAR* argv[]){&&&&&& Student stu1(1,"Li Ming");//对象定义在栈上,所以程序结束时会自动析构哦;&&& Student *pstu2=new Student(2,"Wang qing");//对象定义在堆上,除非delete否则不析构&//(1)&&& return 0;}  上面两种定义都定义了对象,但是执行结果是下面的:  上面没有调用delete删除堆上的对象,所以程序即使结束了,对象是不会自动析构的,这就产生了垃圾;如何这些是一些资源文件或者内核对象,你的程序迟早挂掉;  在(1)处加入delete pstu2;  所以,使用类定义的对象是能够自动析构的;使用类通过new出来的对象,是需要delete的,你不delete,你SOCKET、多线程编程会出问题的。
搜索风云榜
( 00:55:30)
C++中这样的注意事项,可以列上上百条啊。
51Testing官方微信
51Testing官方微博
测试知识全知道C++构造及析构函数执行顺序C++构造及析构函数执行顺序巴厘岛百家号很多小伙伴都老是会碰到疑问,其实还是基础没打扎实,这些题如果你不看答案你能知道多少呢?如果还有很多不知道就证明基础没打扎实,如果你还在入门纠结,如果你还在苦恼怎么入门!小编有个建议,可以加小编弄的一个C语言交流基地,大家可以进入交流基地:,里面新手入门资料,可以说从零到项目实战,都是可以免费获取的,还有程序员大牛为各位免费解答问题,热心肠的小伙伴也是蛮多的。不失为是一个交流的的好地方,小编在这里邀请大家加入我的大家庭。欢迎你的到来。一起交流学习!共同进步!小编等你!前不久,一个朋友面腾讯社招的后台开发岗,和他聊了聊,他说腾讯的一面还是比较重基础的,C++,操作系统,网络、算法这块问的比较多,即便是社招。其中就有一个C++牵涉到虚拟继承时其构造和析构顺序的题目,这个平时也不太注意,因此也真难住了不少面试者,我那位朋友就是其一,因此有必要总结下。在C++中,当创建一个类对象时,编译器是会自动调用一个叫构造函数的东西的,我们知道,C++类与类之间很多情况下是有关联的,比如继承,组合等等,读懂UML类图一文中有描述该主题。本文主要通过实例总结各种情况下的构造与析构顺序。继承场景:B类继承两个父类A和C,每个类的构造函数和析构函数很简单,就是打印对应的函数名,以便观察构造及析构函数执行顺序。通过运行结果可以看出:创造一个子类对象时,先执行父类的构造函数,再执行自身的构造函数,如果子类继承多个父类,则按照继承的顺序从左到右调用父类构造函数(本例先构造A,再构造C),析构的顺序与构造的顺序相反。我们还知道还有一种继承叫做虚拟继承,看看这种情况下的构造与析构又是怎样的顺序。可以看出:虚拟继承和一般的继承构造和析构的顺序还是有点不一样,父类的构造顺序发生了改变,虚拟继承的C构造函数先被执行,然后是A。最后是自身的构造函数被调用,析构的顺序与构造的顺序相反。成员包含其它类对象成员场景:B类含有A类对象和C类对象的成员,且在B类中,其成员声明顺序是先声明c,再声明a。看看创造B类对象时,构造函数和析构函数的执行顺序是怎样的。运行结果可以看出:创造一个B类对象b时,先执行其成员对象所属类的构造函数,再执行自身的构造函数,如果有多个类对象成员,则按照声明的顺序调用对应类的构造函数(本例先构造C类对象c,再构造A类对象a),析构的顺序与构造的顺序相反。即有继承又包含类对象成员场景:B类继承两个父类A和C,并且B类有一个X类的对象成员,观察构造及析构函数执行顺序。运行结果可以看出:类在构造的时候会先从左到右调用父类的构造函数,然后调用类对象成员构造函数,最后调用自身构造函数。析构的顺序与构造的顺序相反。为您提供通俗易懂的技术文章,让技术变的更简单!本文由百家号作者上传并发布,百家号仅提供信息发布平台。文章仅代表作者个人观点,不代表百度立场。未经作者许可,不得转载。巴厘岛百家号最近更新:简介:2017这个世界让人们更精彩作者最新文章相关文章

我要回帖

更多关于 c++虚析构函数 的文章

 

随机推荐