[Reprint]c++ 析构函数的调用

析构函数在调用默认的析构函数和用户自己覆写的析构函数的时候有点意识模糊呢。写段代码总结下

[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、

  • using namespace std;
  • class Box
  • {
  • private:
  • double length;
  • public:
  • Box(double lv=1.0):length(lv)//构造函数都没有返回值
  • {
  • cout << "constructor called" << endl;
  • }
  • ~Box()
  • {
  • cout << "destructor called" << endl;
  • }
  • void showit()
  • {
  • cout << this->length << endl;
  • }
  • };
  • void display(Box box)//关键注意这个地方。。。。。。。。。。。。。。。。。。。。。。。。。
  • {
  • box.showit();
  • }
  • int main()
  • {
  • Box box;
  • display(box);
  • }

运行结果

如果将上面的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],那么复制的只是地址,两个对象公用一个地址,有可能就会造成错误。所以以后需要注意这一点,调用对象需要用引用哦。。。。。(要不你自己另写一个复制函数。)

时间: 2024-11-06 17:13:27

[Reprint]c++ 析构函数的调用的相关文章

c++学习笔记5,多重继承中派生类的构造函数与析构函数的调用顺序(二)

现在来测试一下在多重继承,虚继承,MI继承中虚继承中构造函数的调用情况. 先来测试一些普通的多重继承.其实这个是显而易见的. 测试代码: //测试多重继承中派生类的构造函数的调用顺序何时调用 //Fedora20 gcc version=4.8.2 #include <iostream> using namespace std; class base { public: base() { cout<<"base created!"<<endl; }

C++C++中构造函数与析构函数的调用顺序

http://blog.csdn.net/xw13106209/article/details/6899370 1.参考文献 参考1: C++继承中构造函数.析构函数调用顺序及虚函数的动态绑定 参考2: 构造函数.拷贝构造函数和析构函数的的调用时刻及调用顺序 参考3: C++构造函数与析构函数的调用顺序 2.构造函数.析构函数与拷贝构造函数介绍 2.1构造函数 构造函数不能有返回值 缺省构造函数时,系统将自动调用该缺省构造函数初始化对象,缺省构造函数会将所有数据成员都初始化为零或空 创建一个对象

Effective C++ Item 09-绝不在构造函数和析构函数中调用virtual函数

Item 09-绝不在构造函数和析构函数中调用virtual函数(Never call virtual functions during construction or destruction) Why? 由于base class构造函数的执行更早于derived class构造函数,当base class构造函数执行derived class的成员变量尚未初始化.如果期间调用的virtual函数下降至derived class阶层,要知道derived class的函数几乎必然取用local成

【C/C++】构造函数与析构函数的调用顺序

常见问题 Q1. 以下代码的输出结果是什么? 1 #include <iostream> 2 using namespace std; 3 4 class A 5 { 6 public: 7 A() { cout << "A" << endl; } 8 ~A() { cout << "~A" << endl; } 9 }; 10 class B : public A 11 { 12 public: 13 B

EC笔记,第二部分:9.不在构造、析构函数中调用虚函数

9.不在构造.析构函数中调用虚函数 1.在构造函数和析构函数中调用虚函数会产生什么结果呢? #include <iostream> using namespace std; class cls1{ public: cls1(){ newMake(); }; ~cls1(){ deleteIt(); }; virtual void newMake(){ cout<<"cls1 make"<<endl; } virtual void deleteIt()

绝不在构造和析构函数中调用 virtual 函数

看下面的这段代码,问 print调用的是基类还是派生类的版本? 答案是 基类... 可能大家会很惊讶,print不是virtual function 吗?为什么不是调用派生类的版本呢? 首先,当定义一个派生类的对象的时候, 由于 base class 构造函数的执行更早于 derived class构造函数, 所以当 base class constructor 调用的时候,派生类的成员尚未初始化(说明,这个时候真正的 虚函数表尚未完全初始化). 如果这个时候调用 派生类的函数(可能使用未初始化

C++中构造函数和析构函数的调用顺序

一般而言,析构函数调用的顺序和构造函数调用顺序相反,但是,对象的存储类别可以改变调用析构函数的顺序.举例说明: CreateAndDestroy类的定义 CreateAndDestroy类的成员函数的定义 测试函数 构造函数和析构函数的调用顺序: 分析 全局作用域内定义的对象的构造函数,在文件内任何其他函数(包括main函数)开始执行之前调用,当main函数执行结束时,相应的析构函数被调用,如上面的Object 1. exit函数迫使程序立即结束,不执行自动对象的析构函数.当程序中检测到输入中有

C++:派生类的构造函数和析构函数的调用顺序

一.派生类 在C++编程中,我们在编写一个基类的派生类时,大致可以分为四步: ? 吸收基类的成员:不论是数据成员还是函数成员,派生类吸收除基类的构造函数和析构函数之外的全部成员. ? 改造基类函数:在派生类中声明一个或多个与其(某个)基类中的成员函数同名的成员函数,并将它(们)根据新的需求进行重写 ? 发展新的成员:在派生类中添加新的成员变量和成员函数,其中新添加的成员要求必须和基类中的成员不同名,并且应当保证新添加的成员会使派生类在功能上相比其基类有所发展 ? 重写派生类的构造函数和析构函数

类继承时,构造函数和析构函数的调用次序

比如,apple类是fruit类的子类,当执行apple a("红富士");的时候,将先调用fruit类的构造函数,再调用apple类的构造函数 同理,假设在程序里先后声明了两个apple实例: apple a(“红富士"); apple b("青香蕉"); 当函数退出时,要先销毁b,再销毁a(因为b在栈顶). 而调用析构函数时,先调用apple的析构函数,再调用fruit的析构函数. 综上可见,构造函数和析构函数的调用次序恰好反了个个儿. Java和C+