析构函数基本特点
析构函数是类中特殊的函数。它有如下特点:
- 无返回值
- 无参数
- 函数名与类名相同,前面缀上~
看个粟子:
class A
{
public:
A(){} //A类的构造函数
~A(){} //A类的析构函数
}
析构函数的调用
析构函数在对象被删除时调用。可以说,构造函数伴随着对象的诞生,析构函数伴随着对象的消亡。它用来处理一个对象临终事宜。
看下面例子:
class A
{
public:
A(){cout << "A类构造函数" << endl;}
~A(){cout << "A类析构函数" << endl;}
};
int main()
{
A a;
cout << "~~~~~~~~~~~~~分隔符~~~~~~~~~~~~" << endl;
}
}
运行结果:
在主函数中定义一个对象a
在栈区,定义时调用其构造函数。当主函数结束时,栈区清空,对象a
被删除,此时其析构函数被调用。
除去这种定义的方式,还可以使用new关键字在堆区创建一个对象。根据C++的要求,使用new
关键字创建的对象,必须使用delete
关键字进行删除。 析构函数就是在对象被delete
关键字删除时调用的。
我们对代码主函数稍作修改:
int main()
{
A* pa = new A();
cout << "~~~~~~~~~~~~~分隔符~~~~~~~~~~~~" << endl;
delete pa;
cout << "~~~~~~~~~~~~~分隔符~~~~~~~~~~~~" << endl;
}
结果如下:
默认析构函数与自定义析构函数
当编程者没有编写析构函数时,编译器会提供一个缺省的析构函数。通常来说,这个缺省的析构函数可以在绝大多数情况下满足需求。例如当类成员中包含使用new
关键字创建的类成员时,使用默认的析构函数就不能完美的解决问题了。此时就需要主动实现析构函数来进一步对成员对象进行删除。
将上文代码改进,为A类对象加入一个B类对象:
class B
{
public:
B(){cout << "B类构造函数" << endl;}
~B(){cout << "B类析构函数" << endl;}
};
class A
{
public:
A(){b = new B();cout << "A类构造函数" << endl;}
~A(){cout << "A类析构函数" << endl;delete b;}
private:
B* b;
};
int main()
{
A a;
cout << "~~~~~~~~~~~~~分隔符~~~~~~~~~~~~" << endl;
}
再运行程序,结果如下:
可以看到在这个例子中,A类对象在构造时使用new
关键字创造了一个成员,那么根据上文提到的规定,这个成员必须使用delete
关键字进行删除释放内存。这样的工作就需要放在析构函数中执行。
但由于编译器提供的默认析构函数不会主动对成员指向的内存进行释放,因此在这个情况下如果不主动实现析构函数,程序将只释放成员指针所占内存而并不会释放指向的对象。
何时需要写析构函数
上面的例子给了我们很好地启发,当成员中存在需要显式的进行释放时,就需要在析构函数中完成这项任务了。
当然,析构函数的作用不仅仅在于释放成员中需要释放的内存。倘若需要在一个对象挂掉时进行一些其他的业务处理,那么也是需要写在析构函数中的。
所以写不写析构函数主要还是取决于是否要在对象消亡时进行一些操作,而释放成员内存仅是其中的一种。
啃书系列持续更新ing,关注博主一起学C++鸭~
系列文章:
语言基础部分:
- 啃书《C++ Primer Plus》之 C++ 函数指针
- 啃书《C++ Primer Plus》之 C++ 名称空间1
- 啃书《C++ Primer Plus》之 C++ 名称空间2
- 啃书《C++ Primer Plus》之 C++ 引用
- 啃书《C++ Primer Plus》之 const修饰符修饰 类对象 指针 变量 函数 引用
- 啃书《C++ Primer Plus》之 枚举 内容大全
面向对象部分: