由于delete运算符释放内存,为什么我需要析构函数?

Aqu*_*irl 6 c++ destructor delete-operator

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

记住:delete p有两件事:它调用析构函数并释放内存.

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

raz*_*ebe 13

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

析构函数的要点是执行在对象之后清理所需的任何逻辑,例如:

  • 在被销毁对象拥有的其他对象上调用delete
  • 正确释放数据库连接等其他资源; 文件句柄等

  • @AnishaKaul:嗯......不完全是:行动是逆转的.删除首先调用析构函数(执行代码执行操作,例如删除更多内容,关闭文件或任何内容)然后将对象内存返回给系统. (2认同)

pax*_*blo 9

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

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

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

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

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.
}
Run Code Online (Sandbox Code Playgroud)

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


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

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

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

+-------------------------------------+
| DB connection pool                  |
|                                     |
| +-------------------------+---+---+ |
| | Array of DB connections |   |   | |
| +-------------------------+---+---+ |
|                             |   |   |
+-----------------------------|---|---+
                              |   |   +---------+
                              |   +-> | DB Conn |
             +---------+      |       +---------+
             | DB Conn | <----+         /  |  \
             +---------+         buffers   |   queries
               /  |  \                  caches
        buffers   |   queries
               caches
Run Code Online (Sandbox Code Playgroud)

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

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

像这样的课程:

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

没有真正需要的析构函数,因为内存释放是所有你需要做的.


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

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