今天看书忽然对这个地方有点模糊,尤其是析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢。写段代码总结下

[cpp]  view plain copy
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5. private:
  6. double length;
  7. public:
  8. Box(double lv=1.0):length(lv)//构造函数都没有返回值
  9. {
  10. cout << "constructor called" << endl;
  11. }
  12. ~Box()//重写的析构函数(重写是对继承类对基类的重新构造,这里表述不对)
  13. {
  14. cout << "destructor called" << endl;
  15. }
  16. };//万恶的分号,我老是忘掉

1、首先直接声明(定义)看下

//很多朋友指出我这里用声明不合适,在11楼作了一定解释,具体不在这里赘述,这里改为“定义”,谢谢大家的指正,但我也保留我自己的意见,所以没有把“声明”去掉

[cpp]  view plain copy
  1. int main()
  2. {
  3. Box box(2.3);
  4. }

这里看到一点java与c++的不同点,c++在声明的时候就创建了对象,java声明只是创建一个引用,并不会分配内存。言归正传,说明声明以后就调用了构造函数,然后退出的时候调用析构函数。

2、声明指针

[cpp]  view plain copy
  1. int main()
  2. {
  3. Box *box;
  4. }

可以看到,声明指针并不会调用构造函数,也不会分配内存空间。

3、用new创建

[cpp]  view plain copy
  1. int main()
  2. {
  3. Box *box=new Box(2.3);
  4. }

仅仅是调用构造函数创建了对象,分配了内存空间。但是没有调用析构函数,因为box指定的对象的内存是由new来创建分配的,编译器不能够自动调用析构函数将其删除。所以需要调用delete才可以。

4、用new创建对象,并delete掉

[cpp]  view plain copy
  1. int main()
  2. {
  3. Box *box=new Box();
  4. delete box;
  5. }

这次调用了析构函数。可以看出,此时的析构函数不是编译器自己调用的,是由我们的程序来主动调用的,所以以后需要注意。new了的需要手动释放内存空间

5、什么时候需要重写析构函数?

[cpp]  view plain copy
  1. class Message()
  2. {
  3. private:
  4. char *message;
  5. public:
  6. Message(const char* text="default message")
  7. {
  8. message = new char[strlen(text)+1];
  9. strcpy(message, text);
  10. }
  11. void showit()
  12. {
  13. cout << "message: " << message << endl;
  14. }
  15. ~Message()
  16. };
  17. Message::~Message()
  18. {
  19. cout << "destructor called" << endl;
  20. delete [] message;
  21. }

从例子可以看到,当你的构造函数中调用了new来创建对象的内存分配空间,则需要专门调用delete来释放内存,所以此时需要覆写析构函数,来专门的释放此内存空间

6、对象的形参传值问题:(话外题,仅作记录用)

先看代码及运行结果

[cpp]  view plain copy
  1. #include <iostream>
  2. using namespace std;
  3. class Box
  4. {
  5. private:
  6. double length;
  7. public:
  8. Box(double lv=1.0):length(lv)//构造函数都没有返回值
  9. {
  10. cout << "constructor called" << endl;
  11. }
  12. ~Box()
  13. {
  14. cout << "destructor called" << endl;
  15. }
  16. void showit()
  17. {
  18. cout << this->length << endl;
  19. }
  20. };
  21. void display(Box box)//关键注意这个地方。。。。。。。。。。。。。。。。。。。。。。。。。
  22. {
  23. box.showit();
  24. }
  25. int main()
  26. {
  27. Box box;
  28. display(box);
  29. }

运行结果

如果将上面的display代码改为

[cpp]  view plain copy
  1. void display(Box &box)//改为调用的是引用
  2. {
  3. box.showit();
  4. }

运行结果

可以明显的看到不加引用的时候会出现两个析构函数的调用。为什么呢?

直接传参,是形参传递,所以会另外创建一个对象来复制main函数里的对象box,所以在display调用完成时刻要调用析构函数来释放这个函数创建的形参对象的内存空间。但是如果是传递的引用,就只有一个参数对象了,所以只调用一个。

如果是平时的基本类型,你应该了解,直接把main里的box的值复制给形参box就是了,但是到了对象这里就有点复杂,如果是里面就是单纯的像上面的例子一样double类型等,其自带有复制函数就可以将各个成员值复制到形参对象里,但是如果里面有引用,比如char *pp = new char[100],那么复制的只是地址,两个对象公用一个地址,有可能就会造成错误。所以以后需要注意这一点,调用对象需要用引用哦。。。。。(要不你自己另写一个复制函数。)

转载于:https://www.cnblogs.com/vanishfan/p/3283486.html

C++中构造函数和析构函数调用的时机相关推荐

  1. 2020-12-14(全局/静态对象的构造函数和析构函数调用的时机以及地址)

    一般的对象实例化在什么时候实例化的呢? 是不是在main函数运行到那里的时候,然后创建对象,会调用类里面的构造函数. 那当我们遇到全局/静态对象的时候,它是不是也是需要在main函数里面慢慢构造呢? ...

  2. C++继承中构造函数、析构函数调用顺序及虚析构函数

    首先说说构造函数,大家都知道构造函数里就可以调用成员变量,而继承中子类是把基类的成员变成自己的成员,那么也就是说子类在构造函数里就可以调用基类的成员了,这就说明创建子类的时候必须先调用基类的构造函数, ...

  3. java没有指针和析构所以_Java程序员学习C++之构造函数和析构函数调用的时机

    今天看书忽然对这个地方有点模糊,尤其是析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢.写段代码总结下 #include usingnamespacestd; classBox ...

  4. C++构造函数和析构函数调用虚函数时都不会使用动态联编

    先看一个例子: #include <iostream> using namespace std;class A{ public:A() {show();}virtual void show ...

  5. C++中对象数组的构造函数和析构函数调用

    C++的对象数组 顾名思义,即是存储对象的数组.比如有一个对象A,实例化为对象数组有如下两种方式: A a[3]; //第一种方法,在栈空间中占用内存 A *a = new A[3];//第二种方法, ...

  6. C++构造函数与析构函数调用虚函数的注意事项

    虽然可以对虚函数进行实调用,但程序员编写虚函数的本意应该是实现动态联编.在构造函数中调用虚函数,函数的入口地址是在编译时静态确定的,并未实现虚调用.但是为什么在构造函数中调用虚函数,实际上没有发生动态 ...

  7. C++ 类继承:构造函数与析构函数调用顺序,派生类和基类之间的特殊关系,公有继承及其他

    文章目录 一.派生类构造函数与基类构造函数 二.创建与销毁派生类对象时,构造函数和析构函数的调用 三.派生类和基类之间的特殊关系 四.公有继承 (一).何为公有继承 (二).多态公有继承 (三).虚函 ...

  8. 【C++笔记】构造函数与析构函数相关知识

    目录 一.构造函数和析构函数 二.构造函数的分类及调用 三.拷贝构造函数调用时机 四.构造函数调用规则 五.深拷贝与浅拷贝 六.初始化列表 七.类对象作为类成员 八.静态成员 每个对象需要有初始设置以 ...

  9. php中的构造函数和析构函数,php 中构造函数和析构函数

    构造函数: 在对象实例化时被调用,一个类中只能有一个构造函数,在类中起初始化的作用. 析构函数: 在对象结束时被自动调用. 话不多说,用一段代码来说明两者的区别: //定义一个类 class Pers ...

最新文章

  1. Spring Cloud Hystrix理解与实践(一):搭建简单监控集群
  2. objdump反汇编用法示例
  3. 【控制】《复杂运动体系统的分布式协同控制与优化》-方浩老师-第10章-基于模型预测控制的人机协同控制
  4. 武汉大学linux课程,武汉大学超算中心
  5. 【云速建站】后台配置邮费
  6. Linux设备树 .dtb文件,内核使用dtb文件的过程
  7. 在Windows平台下实现《简明 Python 教程》第十章案例(利用winrar实现压缩备份)...
  8. 微信微调助手WeChatTweak for mac(微信多开和防撤回工具)最新版
  9. Spring框架入门程序:获取Bean的三种方式
  10. 分享2个Python处理Excel的脚本
  11. 魔兽单机服务器修改升级属性,魔兽世界单机版怎么调整人物级别(用户使用)?20分...
  12. HTTP 415错误
  13. WinEdt 9 如何与pdf打开软件(Acrobat)关联
  14. Php替换公众号图片替换,公众号文章发布后可以替换图片吗?公众号发出去的图片怎么替换?...
  15. 【Arcpy】批量合并重叠拓扑
  16. cle IMP-00015: 由于对象已存在, 下列语句失败
  17. 曙光LINUX是什么系统,国产操作系统的曙光----深度操作系统Deepin
  18. AUTOSAR MCAL解析:Wdg
  19. vs2013怎么清理解决方案_vs2010/2013项目所在文件夹越来越大如何解决?
  20. 4G图传数传一体机GSLINK实测20180930

热门文章

  1. 干货精讲!java分布式事务框架
  2. 2014秋季新款韩版潮流女装黑白拼色气质一字领打底收腰显瘦连衣裙F506
  3. 天翼云弹性计算服务器,获取天翼云Windows弹性云主机的密码操作步骤
  4. 如何成为技术大神(文末有抽奖)
  5. 随记-简单而优雅的 namedtuple
  6. 【yum】yum “Status code: 404 for http:”错误
  7. wps英文文档排版小技巧
  8. MySQL认证介绍 (转帖)
  9. Js如何删除所有子元素以及当前元素
  10. MVC有哪几种过滤器?