c – 当删除操作符释放内存时,为什么需要析构函数?

来自c FAQ:http://www.parashift.com/c++-faq-lite/dtors.html#faq-11.9

Remember: delete p does two things: it calls the destructor and it deallocates the memory.

如果删除释放内存,那么析构函数需要什么?

最佳答案
你需要调用析构函数,以防除了分配内存之外还需要做其他事情.

除了非常简单的课程,通常都有.

关闭文件句柄或关闭数据库连接,删除对象中成员数据指向的其他对象等等.

一个典型的例子是堆栈的实现:

class myStack {
    private:
        int *stackData;
        int topOfStack;

    public:
        void myStack () {
            topOfStack = 0;
            stackData = new int[100];
        }

        void ~myStack () {
            delete [] stackData;
        }

        // Other stuff here like pop(), push() and so on.
}

现在想想如果每次删除一个堆栈时都没有调用析构函数会发生什么.在这种情况下,C中没有自动垃圾收集,因此stackData内存会泄漏,最终会耗尽.

这要求析构函数删除其所有资源,从树向下移向基本类型.例如,您可能拥有一个包含数据库连接数组的数据库连接池.析构函数将删除每个单独的数据库连接.

单个数据库连接可能会分配很多东西,例如数据缓冲区,缓存,编译的SQL查询等.所以数据库连接的析构函数也必须删除所有这些东西.

换句话说,你有类似的东西:

+-------------------------------------+
| DB connection pool                  |
|                                     |
| +-------------------------+---+---+ |
| | Array of DB connections |   |   | |
| +-------------------------+---+---+ |
|                             |   |   |
+-----------------------------|---|---+
                              |   |   +---------+
                              |   +-> | DB Conn |
             +---------+      |       +---------+
             | DB Conn | <----+         /  |  \
             +---------+         buffers   |   queries
               /  |  \                  caches
        buffers   |   queries
               caches

释放数据库连接池的内存不会影响单个数据库连接或它们指向的其他对象的存在.

这就是为什么我提到只有简单的类可以在没有析构函数的情况下逃脱,而那些类往往会出现在上面那棵树的底部.

像这样的课程:

class intWrapper {
    private:
        int value;
    public:
        intWrapper () { value = 0; }
        ~intWrapper() {}
        void setValue (int newval) { value = newval; }
        int getValue (void) { return value; }
}

因为内存释放是您需要做的所有事情,因此不需要析构函数.

底线是新的和删除是同一极的两端.首先调用new分配内存然后调用相关的构造函数代码以使对象处于可操作状态.

然后,当你完成后,删除调用析构函数“拆除”你的对象,回收为该对象分配的内存.

转载注明原文:c – 当删除操作符释放内存时,为什么需要析构函数? - 代码日志