`

《C++学习笔记》析构函数(destructor)

    博客分类:
  • C++
阅读更多
===============================================
未完待续,转载时请表明出处:http://www.cofftech.com/thread-1395-1-1.html
欢迎大家跟帖讨论哈~~~~~
===============================================

用户所定义的析构函数主要用于释放在建立对象时构造函数从堆区中分配的空间。
和构造函数相同,只当用户在类中定义了析构函数后,程序删除对象时系统才调用析构函数。
析构函数是类的特殊成员函数,它的名字也与类名相同,只是在前面加一个符号“~”。析构函数没有任何参数,也不返回任何值。
[例1]析构函数的用途
#include <string.h>
#include <iostream.h>
class string
{
       char *contents;
       int size;
public:
       string(int sz) {
         size = sz;
         contents = new char[sz];
         cout<<"constructor "<<size<<endl;     }
       ~string() {    delete [ ]contents;
                            cout<<"destructor "<<size<<endl;   }
};
void main( )
{
       string s1(10), s2(20);
}
/* Results:
       constructor 10
       constructor 20
       destructor 20
       destructor 10                     */
以上程序中,建立对象时系统调用构造函数,在堆区内分配了一定空间;程序结束时系统删除对象,自动调用析构函数,将所分配的空间释放,退还给堆区。
从以上程序还可看出:
析构函数的调用顺序正好与构造函数的调用顺序相反。
前面提到,如已定义析构函数,则删除对象时将自动调用析构函数,因此,如对象是在一个函数或一个程序块内建立的,则在退出该函数或程序块时,将会删除该对象,从而自动地调用析构函数,见下例。
[例2] 退出程序块和函数时都删除对象,因而都调用析构函数
#include <iostream.h>

class point {
     int j;
public:
     point ( int i ) {    j = i;
            cout<<"Cons"<<j<<endl;        }
     ~point ( )      {     cout<<"Des"<<j<<endl;          }
};

void main()
{
     point objm(1);
     {             //为教学目的而设的程序块
  point objb(2);
  cout<<"end of block"<<endl;
     }
     cout<<"end of program!"<<endl;
}

/* Results:
Cons1
Cons2
end of block
Des2
end of program!
Des1           */
还须指出,有时用户不在类中定义构造函数,但却定义了析构函数。虽然程序建立对象时系统并不调用构造函数;但在程序结束时系统自动删除对象,就会调用析构函数。
现在利用析构函数来再次了“按数值调用”和“按引用调用”时形参的不同处理方式。
在阅读下列程序之前,先熟悉一下对象用作形参和返回值的格式。我们已熟悉:
int  fun( int i )
{
        return  i;
} 的形式。
但不熟悉:
AA  fun( AA  obj )
{
        return  obj;
} 的形式。
将两者对比一下,就容易看出,前例中形参是预定义类型int变量i,而后例中形参是class AA的对象obj。
    函数调用方式,其中“按数值调用”方式将实参复制为副本并将其推入堆栈,而“按引用调用”方式则不复制实参而只将实参的指针(即地址)复制为副本并将其推入堆栈。 如果其实参是类的对象,则“按数值调用”方式将建立新的临时对象并将其推入堆栈,而“按引用调用”方式则只复制对象的指针。这点可从以下程序看出。
[例3] // destructor_3.cpp
// To differentiate between two modes: "call-by-value" and "call-by-reference"
#include <iostream.h>

class AA {
public:
       int a;
       AA (int x)     { a = x;
              cout<<"Cons-"<<a<<endl;             }
       ~AA ( )
       { cout<<"Des-"<<a<<endl;            }   
};

void inc_by_value(AA obj)     //形参是class AA的对象obj
{
       obj.a++;
       cout<<"program inc_by_value ended!"<<endl;
}

void inc_by_refer(AA & obj)  //形参是class AA的对象obj的引用,实即指针
{
       obj.a++;
}

void main()
{
       AA  obj(10);
       inc_by_value(obj);
       cout<<"call_by_value:a="<<obj.a<<endl;
       obj.a = 20;
       inc_by_refer(obj);
       cout<<"call_by_reference:a="<<obj.a<<endl;
       cout<<"program main ended!"<<endl;
}

/* Results:
Cons-10
program inc_by_value ended!
Des-11
call_by_value:a=10
call_by_reference:a=21
program main ended!
Des-21
*/
以上程序中定义了构造函数和析构函数。在“按数值调用”中,由系统为实参(class AA的对象)在堆栈上产生副本(也即建立新的临时对象并复制所有非静态数据),并不调用构造函数。当对函数inc_by_value( )的调用结束时,对象副本(即临时对象)被删除,从堆栈中消失,因而它的析构函数被立即调用。
而在“按引用调用”中,引用作为“别名其表,指针其实”,实参不需要产生对象副本而只产生指针副本(也即不建立临时对象)。因此在调用函数inc_by_refer( )时不须要建立临时对象,在退出函数时也不删除任何对象,也就不会调用析构函数,这种调用方式减少了空间和时间上的开销。
分享到:
评论

相关推荐

    C#析构函数

    析构函数 finalizer destructor 整理的关于析构函数的描述以及介绍

    全面解读C#编程中的析构函数用法

    析构函数用于析构类的实例。 备注 不能在结构中定义析构函数。只能对类使用析构函数。 一个类只能有一个析构函数。 无法继承或重载析构函数。 无法调用析构函数。它们是被自动调用的。 析构函数既没有修饰符,也没有...

    详解C++编程中的析构函数

    C++析构函数 创建对象时系统会自动调用构造函数进行初始化工作,同样,销毁对象时系统也会自动调用一个函数来进行清理工作(例如回收创建对象时消耗的各种资源),这个函数被称为析构函数。 析构函数(Destructor)...

    C++ 析构函数与变量的生存周期实例详解

    这篇介绍了析构函数,是我的读书笔记,我希望它够简短但又比较全面,起到复习的作用。如果有一些C++知识记不清楚了,它可以帮你很快回忆起来。 析构函数(destructor)的名字与类名相同,但是前面要加“~”。析构...

    C++虚基类 虚函数 虚析构函数

    //析构函数做成员函数 }; Base::~Base()//成员函数实现 { cout&lt;&lt;"Base destructor"; } class Derived:public Base { public: Derived(); ~Derived(); private: int *p; }; Derived::Derived() { p=new int(0);//...

    浅谈C++基类的析构函数为虚函数

    1、原因:  在实现多态时, 当用基类指针操作派生类, 在析构... Output from the destructor of class Base! &lt;&lt; endl;};  void DoSomething() { cout &lt;&lt; Do something in class Base! &lt;&lt; endl;

    C++中确定基类有虚析构函数

    本文给大家介绍了C++中确定基类有虚析构函数的方法。

    C++构造函数与析构函数

    实验指导 1)掌握构造函数和析构函数定义方法; 2)掌握构造函数的重载、具有默认值的构造函数的使用方法; 3)加深对构造函数的特殊用途的理解。

    ruby-destructor:Ruby 的析构函数

    析构函数 这将新的回调添加到实例对象,例如 :initialize,但会产生相反的效果:finalize 安装 将此行添加到应用程序的 Gemfile 中: gem 'destructor' 然后执行: $ bundle 或者自己安装: $ gem install ...

    stack_unwinding:stack_unwinding是仅用于C ++的小型头文件库,它提供原语(unwinding_indicator类)来确定何时由于堆栈展开或正常作用域离开而调用对象析构函数

    stack_unwinding是一个仅用于标头的小型C ++库,它提供原语(类unwinding_indicator)来确定何时由于堆栈展开或正常作用域离开而调用对象析构函数。 unwinding_indicator包含在单个头文件中: 在unwinding_...

    新手学习C++入门资料

    C++函数的原型中可以声明一个或多个带有默认值的参数。如果调用函数时,省略了相应的实际参数,那么编译器就会把默认值作为实际参数。可以这样来声明具有默认参数的C++函数原型: #include iostream.h void show...

    Effective+C+++3rd+chm+中文版(代码加亮)

    destructor(析构函数)什么时候应该是 virtual(虚拟)的?当 operator new(运算符 new)找不到足够的内存时它应该怎么办?类似这些的令人费神的细节是至关重要的,因为错误的做法几乎总是导致无法预料的,很可能...

    More Effective C++.pdf

    某些小范围主题诸如「在base classes 中使用virtual destructor」、「令operator= 传回*this 的reference」,可能在百科型C++ 语言书籍中亦曾概略提过,但此类书籍以深度探索的方式,让我们了解问题背後的成因、最佳...

    More Effetive c++

    C++ 是一个难学易用的语言! C++ 的难学,不仅在其广博的语法,以及语法背後的语意,以及语意背後的深层思维,以及深层思维 背後的物件模型;C++ 的难学,还在於它提供了四种不同(但相辅相成)的程式设计思维模式:...

    第七次实验报告1

    (2) 当析构函数设置为virtual时(一般只需在顶级父类中声明即可),其调用的将会是真实对象的destructor,然后系统一级级地撤销父类的资源 (3)

    C++继承

    子类的默认成员函数 构造函数 先调用父类的默认构造, 初始化父类的成员 再调用子类的构造, 初始...析构函数: 在底层都是 : destructor * 会造成同名隐藏 子类析构不要调用父类的析构 菱形继承 : 数据冗余 二义性(钻石

    More Effective C++(中文版)

    某些小范围主题诸如「在base classes 中使用virtual destructor」、「令operator= 传回*this 的reference」,可能在百科型C++ 语言书籍中亦曾概略提过,但此类书籍以深度探索的方式,让我们了解问题背后的成因、最佳...

    巴特沃斯带通滤波器matlab代码-DSPTools:音频DSP工具,用于在MacOSX上进行音频编程

    许多伪类允许在类类型之前使用下划线,以指示变量超出范围时对类析构函数的自动调用。 void myFunction() { _Matrix *myMatrix = Matrix_new(4,4); } //Destructor called here... 此代码中包含许多测试文件,这些...

    Google C++ Style Guide(Google C++编程规范)高清PDF

    Beware of destructors, which are often longer than they appear because of implicit member- and base-destructor calls! Another useful rule of thumb: it's typically not cost effective to inline ...

    More Effective C++

    某些小范围主题诸如「在base classes 中使用virtual destructor」、「令operator= 传回*this 的reference」,可能在百科型C++ 语言书籍中亦曾概略提过,但此类书籍以深度探索的方式,让我们了解问题背後的成因、最佳...

Global site tag (gtag.js) - Google Analytics