当删除运算符释放内存时,为什么需要析构函数? [英] As the delete operator deallocates memory, why do I need a destructor?

查看:235
本文介绍了当删除运算符释放内存时,为什么需要析构函数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

来自c ++常见问题解答: http://www.parashift .com / c ++-faq-lite / dtors.html#faq-11.9

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


记住:删除p有两件事:

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

如果delete取消了内存分配,那么这里的析构函数又有什么需要?

If delete deallocates the memory, then what's the need of the destructor here?

推荐答案

您需要调用析构函数,以防除取消分配内存以外还有其他需要完成的事情。

You need to call the destructor in case there are other things that need to be done other than just de-allocating memory.

除了非常简单的类之外,通常还有其他类。

Other than very simple classes, there usually are.

诸如关闭文件句柄或关闭数据库连接,删除操作之类的事情

Things like closing file handles or shutting down database connections, deleting other objects that are pointed to by members data within your object, and so forth.

经典示例是堆栈的实现:

A classic example is the implementation of a stack:

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 内存会泄漏,最终您将耗尽。

Now think of what would happen if the destructor was not called every time one of your stacks got deleted. There is no automatic garbage collection in C++ in this case so the stackData memory would leak and you'd eventually run out.

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

This requiring of a destructor to delete all its resources moves down the tree towards the basic types. For example, you may have a database connection pool with an array of database connections. The destructor for that would delete each individual database connection.

单个数据库连接可能会分配很多东西,例如数据缓冲区,缓存,已编译的SQL查询等。因此,用于数据库连接的析构函数还必须删除所有这些内容。

A single database connection may allocate a lot of stuff, such as data buffers, caches, compiled SQL queries and so on. So a destructor for the database connection would also have to delete all those things.

换句话说,您拥有

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

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

Freeing the memory for the DB connection pool would not affect the existence of the individual DB connection or the other objects pointed to by them.

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

That's why I mentioned that only simple classes can get away without a destructor, and those are the classes that tend to show up at the bottom of that tree above.

像这样的类:

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

对于析构函数没有真正的 需求,因为

has no real need for a destructor since the memory deallocation is all you need to do.

最重要的是 new

The bottom line is that new and delete are opposite ends of the same pole. Calling new first allocates the memory then calls the relevant constructor code to get your object in a workable state.

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

Then, when you're done, delete calls the destructor to "tear down" your object the reclaims the memory allocated for that object.

这篇关于当删除运算符释放内存时,为什么需要析构函数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆