2013-07-15 61 views
0

何时必须在C++类中定义析构函数,为什么?什么时候必须要在C++类中定义析构函数,为什么?

刚开始在C++中学习,需要澄清它。

+0

可能出现[三条法则是什么?](http://stackoverflow.com/questions/4172722/what-is-the-rule-of-reeree)。不是一个确切的副本,但任何人提出这个问题都会通过学习三条规则来了解他们应该知道的内容。 – Nemo

+0

我不认为这是一个糟糕的问题,肯定是一个初学者的问题,但它不是一个主观问题,至少 – aaronman

回答

5

如果你的类需要做特殊的清理,比如释放动态分配的内存,那么你只需要定义一个析构函数。

+6

或者它是否会被继承,哪一个需要虚拟析构函数 – dchhetri

3

当你有动态分配的内存时,你需要定义一个析构函数。一个好的经验法则是如果你在你的构造函数中使用new,你可能需要一个析构函数。凡是不自动存储或静态存储被视为动态分配

任何会落入清理的类别下是适当放的析构函数,例如关闭网络连接

+2

这是最常见的情况,但目前并非唯一。你可能也想在析构函数中关闭班级管理的网络连接。 – celtschk

+0

@celtschk对于初学者我认为这已经足够好了,我不认为joe需要担心网络连接 – aaronman

+0

@celtschk我也说过需要,尽管在析构函数中关闭一个连接也是适当的,在删除之前调用的关闭方法 – aaronman

1

有可能是其他原因,但我想到的第一个问题是,你的某些类属性可能需要明确释放。

如果你的类只有两个int属性,那么当你调用delete myObject时,这些属性将自动与对象一起被删除。但是,如果它包含任何动态分配的属性,那么这些属性将不会与对象一起释放,因此您需要在析构函数中明确删除它们。

+0

除非它们由智能指针处理(它们应该是这样)。 – celtschk

1

如果析构函数的默认行为不是你想要的,你只需要定义一个析构函数。

当一个对象被销毁,析构函数做这些事,不管你自定义一个析构函数或不:

  • 要求每个数据成员的析构函数。
  • 调用每个基地的析构函数。

这实际上处理了你可能想要做的大多数事情。它曾经是常见的自定义一个析构函数时内存在构造函数中被分配:

struct A { 
    B *b_ptr; 

    A() : b_ptr(new B) { } 
    ~A() { delete b_ptr; } 
}; 

但是当你使用标准集装箱和智能指针,你需要一个自定义的析构函数的案件数量相对较少。举例来说,如果你有这样

struct A { 
    std::unique_ptr<B> b_ptr; 

    A() : b_ptr(new B) { } 
}; 

一类是没有必要定义自己的析构函数,因为的std ::的unique_ptr将释放分配的内存。同样的,也没有必要界定,因为这里input_stream

struct B { 
    ifstream input_stream; 

    B(const std::string &path) : input_stream(path) { } 
}; 

析构函数时INPUT_STREAM成员被破坏将自动关闭。

有时候,你需要做一些特殊的事情。您需要特殊的电话才能获取或释放资源。在这种情况下,你想有一个析构函数:

struct C { 
    ResourceHandle resource_handle; 
    C() : resource_handle(resouce_manager.acquireResource()) { } 
    ~C() { resource_manager.releaseResource(resource_handle); } 
}; 

但是尽可能多的,你要本地化的这种行为,使其不具备在许多类中复制。例如,你可能想使类是这样的:

struct ResourceHolder { 
    ResourceHandle resource_handle; 
    ResourceHolder() : resource_handle(acquireResource()) { } 
    ~ResourceHolder() { releaseResource(resource_handle); } 
}; 

现在你可以只使用一个ResourceHolder每个需要这些资源的一个类中,你永远不会有重复的获取和再次释放逻辑。

+0

对于这个问题工作太多 – aaronman

0

析构函数不仅用于释放分配的内存,例如在构造函数中。

您可以通过使用析构函数实现RAII-style功能。的该利用此类型

实施例:

std::fstream关闭打开的文件

std::lock_guard解锁互斥

std::shared_ptr递减一个基准计数器或自由存储器如果计数器是0

0

有2个实例需要定义析构函数:

  1. 你正在你的类的某个地方分配资源,也考虑拷贝构造函数和赋值操作符,即使它阻止它们被使用,你也可能需要定义它们。
  2. 该类将从中派生。在这种情况下,析构函数必须是虚拟的。原因是如果派生类将使用引用或指向包含派生类实例的父类的指针来析构,派生类的析构函数将不会被调用。
相关问题