缺少析构函数声明

时间:2014-01-13 10:16:50

标签: c++ memory destructor

如果我忘记在C ++类中声明destrucor,有人能告诉我对象的内存会发生什么吗?我的意思是,它是否被释放或导致内存泄漏? 一个例子或演示将不胜感激。

提前致谢。

3 个答案:

答案 0 :(得分:4)

为任何非平凡的类定义析构函数通常被认为是一种好习惯(参见Rule of Three)。但是,在现代C ++(即C ++ 11以后版本)中,它并不像以前那样必要。

如果您的类不是从其他任何东西继承的,那么编译器提供的默认析构函数将正确销毁任何直接成员(例如变量和对象)。同样,如果您的对象拥有任何堆积分配的包装在智能指针中的对象,它们也将被安全地销毁。

如果您的对象通过原始指针拥有任何堆分配的数据,则会出现问题。隐式析构函数无法知道如何处理它们,因此您需要一个自定义析构函数来清除它们。例如:

class MyClass
{
    int m_data1;
    std::string m_data2;
    std::shared_ptr<Widget> m_data3;
    Widget *m_data4;
};

在上面的示例中,成员m_data1m_data2m_data3都将在没有自定义析构函数的情况下正确清除。但是,m_data4指向的对象将自动清除。如果它是由MyClass分配的,那么它通常会导致内存泄漏(除非它被其他东西释放)。

所有这些都表明,继承会以一种重要的方式改变事物。如果你的类继承了其他任何东西,那么你应该总是给它一个虚拟析构函数。如果您的对象是通过指向继承类的指针删除的,并且该类具有虚拟析构函数,那么将永远不会调用子类的析构函数,从而可能导致内存泄漏。

例如:

class Parent
{
public:
    Widget m_data1;
}

class Child : public Parent
{
public:
    Widget m_data2;
}

int main()
{
    Parent *ptr = new Child;
    delete ptr; // <-- clears-up Parent but not Child
}

在上面的示例中,ptr属于Parent类型,因此delete只知道对象的Parent部分。这意味着只有m_data1才能正确清除。如果没有虚拟析构函数,它就不知道对象的Child部分,因此m_data2将无法正确清除(它的析构函数永远不会被调用)。

答案 1 :(得分:2)

如果未声明析构函数,编译器将生成析构函数,该析构函数将调用对象的所有成员的析构函数。只有在使用原始内存(C文件,内存分配等)时才会出现泄漏。

答案 2 :(得分:2)

这取决于班级的数据成员。如果类管理资源,那么它需要一个析构函数来释放它们(你还应该提供一个复制构造函数和赋值运算符,或者使该类不可复制且不可赋值)。

如果类具有内置数据成员或管理自己资源的数据成员,那么隐式生成的析构函数就足够了。它将调用所有数据成员的析构函数。