析构函数中需要使用delete吗?

10

以下是我的代码,我想知道这里的 delete b 是否必要?我的操作系统会自动清除分配的内存区域吗?

class A
{
    B *b;

    A()
    {
        b = new B();
    }

    ~A() 
    {
        delete b;
    }
};

非常感谢。


6
"A" 还需要一个拷贝构造函数和赋值运算符。 - GManNickG
9个回答

13

是的,您必须删除您拥有的每个使用new创建的对象。在此情况下,似乎class A拥有该class B的实例并负责调用delete

最好使用智能指针来管理class B实例的生命周期。另外请注意,在class A中,您必须实现或禁止赋值运算符和复制构造函数,以防止浅拷贝对象,这将带来很多麻烦。


5

可能你的操作系统会在程序退出时释放已分配的内存,但是长时间运行的程序会遇到内存问题。

使用智能指针来动态分配对象总是一个好主意,这些指针将为您处理所有删除操作。

  • std::auto_ptr
  • boost::shared_ptr
  • boost::scoped_ptr

2

你的写法当然是必要的。即使有delete,这个类仍然存在根本性的缺陷,因为它管理着一个资源,但没有遵循三大法则

话虽如此,手动内存管理几乎肯定没有必要——很少有情况需要。你可能应该将B对象作为成员变量,或者使用像QScopedPointer这样的智能指针:

struct A
{
    QScopedPointer<B> b;
    A() : b(new B()) { }

    // No ~A() needed; when the A object is destroyed, QScopedPointer ensures 
    // that the B object pointed to by the member 'b' is destroyed and deleted.
};

您需要确保拥有一本好的C++入门书籍,以便学习如何编写正确的C++程序。


2

如果你调用了new,相应的delete是必须的。

至于操作系统删除内存,是的,它会发生,但只有在整个进程终止(即你的应用程序退出)后才会发生。只有在此之后,操作系统才会回收所有内存和其他资源。

第三点,尽可能只在必要时使用new/delete。在你的情况下,你可以直接写

class A 
{

B b;

  A() {}

  ~A() {}

};

它会产生相同的效果,而且您可以避免额外的动态内存分配。

1

它只会在进程结束时清除区域,但该区域将始终保留分配状态直到进程结束,这意味着存在内存泄漏的风险。


1

b 成员将在堆上分配。操作系统确实会释放堆占用的所有内存;但是这只会发生一次:在程序退出时

因此,如果您不在它们变得无用的那一刻(通常在某个对象的析构函数中)释放已分配的堆块,则有可能出现内存泄漏

所以基本答案是:是的,您必须手动调用delete,因为内存不会立即自动释放(尽管智能指针可以帮助您实现类似的功能)。


1

使用new分配的任何内容都应该使用delete释放,否则您的应用程序中会存在内存泄漏。

在大多数现代操作系统上(特别是人们通常在桌面计算机上运行的操作系统),进程使用的任何内容都将在进程结束时清除,因此如果您忘记了delete,那么内存将被自动释放。但是,您不应该依赖于这一点。

很久以前,我在C语言中编写Amiga的程序。它的操作系统比今天的操作系统要简单得多。如果您分配了内存并没有释放它,在关闭或重新启动计算机之前,它将保持分配状态,即使进程已经结束。当时,内存泄漏问题更加严重。


1

资源管理不仅仅是释放内存。是的,大多数平台会在进程结束时释放您分配的任何内存,而且内存足够便宜,也许您一段时间内都不会注意到。但是,如果文件b正在打开,或者互斥量将在其析构函数中解锁,那么怎么办?在耗尽内存之前,您可能会遇到让对象超出其有用性的问题。


0

1) 长期运行的应用程序会遇到问题,因为操作系统只能在应用程序停止运行时收回内存。

2) delete b;也会导致所指向的B实例的析构函数运行。否则,它将永远不会运行,因为再也无法访问它了。那个析构函数可能会执行一些重要操作。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接