1

假设您有这样的课程

  class Level
  {
    public:

     Level(std::string);
     ~Level();

    private:
     Bitmap* map;  
  }

在课堂上你有这个

Level::Level(std::string)
{
  map = new Bitmap(path);
}

想知道你能打电话吗

Level::~Level()
{
 delete map;
}

因为我担心课程是否超出范围并且我没有删除地图。那么,这不会导致内存泄漏。我是否必须手动调用才能删除地图。如果我在程序的构造函数中调用 delete,我会崩溃。

就像我可以在 Level 中添加一个名为 say destroy map 的方法,我在其中删除地图。但是,想知道为什么我不能将删除添加到析构函数中。

4

6 回答 6

4

Level对象超出范围时,将调用其析构函数,因此释放内存很有用,因为不再需要该内存。您还可以使用 a unique_ptr,从而自动执行内存释放。

于 2013-11-06T01:17:37.287 回答
3

答案已经指出,当你的对象超出范围时,你可以相信你的析构函数会被调用。我不会重申这一点。我只是想指出没有必要分配你Bitmapnew(除非你使用自定义内存分配器,这里不是这种情况)。您可以使用初始化列表构造它:

class Level
{
  public:
    Level(std::string);

  private:
     Bitmap map;  
};

Level::Level(std::string)
    : map(path)
{
}

现在它具有自动作用域,您不必担心您的析构函数。

于 2013-11-06T01:24:59.267 回答
3

这就是为什么析构函数代表。当您的对象超出范围(内存驻留在堆栈对象上)或被delete调用时(对于动态分配的对象),显式调用析构函数,以便释放对象保留的内存。如果要在销毁时释放成员对象的内存,可以使用delete(或delete[]用于数组)调用每个对象的析构函数。最好使用智能指针,以避免无意的内存泄漏并确保在所有情况下都正确释放内存,因为它们使用 RAII 概念(RAII 和 C++ 中的智能指针)。

于 2013-11-06T01:20:34.123 回答
2

这基本上是对的。

然而:

  • 如果您以这种方式管理内存,您还需要确保创建一个复制构造函数和赋值运算符。(这就是你的崩溃的来源。)

  • 另一种最好的方法是使用RAII并且不存储原始指针,而是存储范围或自动指针。甚至只是一个直接封装的对象!然后你根本不需要delete

于 2013-11-06T01:28:02.373 回答
0

因为我担心课程是否超出范围并且我没有删除地图。那么,这不会导致内存泄漏。

你是对的 - 你应该delete map完全按照你的代码做。但是,您还应该使您的对象不可复制(从 boost 或 C++11 不可复制基类派生,或添加operator=复制分配和复制构造函数的私有声明(没有定义/实现)。否则,如果您(故意或意外或偶然 - 例如,当将您的对象存储在有时会复制它的容器中时,例如 a std::vector) 复制您的对象,然后析构的第一个副本将deletemap任何其他尝试使用它的副本都可能崩溃,以及任何其他副本的析构函数也尝试delete它也将具有未定义的行为。

我是否必须手动调用才能删除地图。

是的,在你的代码中你这样做。

更好的选择是使用智能指针,其自身的析构函数将删除指向的对象。

如果我在程序的构造函数中调用 delete,我会崩溃。

好吧,如果你delete在 之后调用new,那么构造函数不会崩溃,但是map在构造函数返回后你将没有要使用的对象,如果你在析构函数中再次尝试delete它,你会得到未定义的行为,这很可能表现为崩溃。

delete如果有时您想比析构函数更早地映射,您可以将指针设置为,NULL以便未来delete不会安全地执行任何操作。然后,您应该在尝试使用map.

就像我可以在 Level 中添加一个名为 say destroy map 的方法,我在其中删除地图。但是,想知道为什么我不能将删除添加到析构函数中。

如上所述,您可以拥有destroy_map,但它必须与析构函数协调。

当没有令人信服的理由不这样做时,最好制作map成员数据,而不是通过引用存储它。当指针有用时,尽可能使用智能指针。如果要实现显式手动内存管理,请注意上述问题。

于 2013-11-06T01:28:48.763 回答
-3

这是一种不寻常的方法。通常,对象的生命周期是由对象之外的因素决定的。

但实际上 MFC 曾经(现在仍然如此?)在 Window 被销毁时会这样做。(我相信是对 WM_NCDESTROY 的回应。)这可确保您在窗口消失后不会让 Window 实例泄漏内存。

所以我会说它在某些情况下是有效的。你可以称之为阶级自杀!

于 2013-11-06T01:18:58.923 回答