1

Let say you have a class like this

  class Level
  {
    public:

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

    private:
     Bitmap* map;  
  }

and in the class you had this

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

Was wondering do can you call

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

As I was worried about if the class goes out of scope and I haven't deleted map. Then, wouldn't that cause a memory leak. Do I have to manually call to delete map. As I get crash if I call delete in the constructor in my program.

Like I could add a method to Level called say destroy map where I delete map. But, was wondering why I can't add delete into the destructor.

simplicity
  • 117
  • 1
  • 6

6 Answers6

4

When the Level object goes out of scope, its destructor will be called, so deallocation of memory is useful because that memory is no longer needed. You can also use a unique_ptr, whereby memory-deallocation performed automatically.

David G
  • 94,763
  • 41
  • 167
  • 253
3

This is why destructors stand for. Destructor is explicitly called when your object goes out of scope (memory residing on the stack objects) or when delete is called ( for dynamically allocated objects), so that the memory the object kept would be released. If you want to release member objects memory when destroyed, you can call the destructors of each object using delete (or delete[] for arrays). It is better that you use smart pointers, to avoid unintentional memory leaks and to ensure the memory is freed correctly in all cases, as they use RAII concept (RAII and smart pointers in C++).

Community
  • 1
  • 1
Nick Louloudakis
  • 5,856
  • 4
  • 41
  • 54
  • But, I know it will delete say Level. But, I was worried if they delete the memory I've created in the class Level. – simplicity Nov 06 '13 at 01:25
  • Who would delete that? The pointer has private storage, so only your class is allowed to access it. – paddy Nov 06 '13 at 01:28
  • 1
    @NickL.: _Destructor explicitly calls delete_ I thought it's the other way around. When the object is `delete`d, the destructor is called and the memory allocated is reclaimed. – legends2k Nov 06 '13 at 01:34
3

Answers already have pointed out that you can trust your destructor to be called when your object goes out of scope. I won't reiterate that. I just wanted to point out that there is no need to allocate your Bitmap with new (unless you were using custom memory allocators, which is not the case here). You can construct it with an initialiser list:

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

  private:
     Bitmap map;  
};

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

Now it has automatic scope and you don't have to worry about your destructor.

paddy
  • 60,864
  • 6
  • 61
  • 103
2

That's basically right.

However:

  • You need to make sure you create a copy constructor and assignment operator too, if you are managing memory this way. (That's where your crash comes from.)

  • An alternative, the best way, is to use RAII and store not a raw pointer but a scoped or automatic pointer. Or even just a directly encapsulated object! Then you don't need the delete at all.

Lightness Races in Orbit
  • 378,754
  • 76
  • 643
  • 1,055
0

As I was worried about if the class goes out of scope and I haven't deleted map. Then, wouldn't that cause a memory leak.

You're right - you should delete map exactly as your code does. But, you should also make your object non-copyable (derive from boost or C++11 noncopyable base classes, or add a private declaration (with no definition/implementation) of the operator= copy assignment and copy constructor. Otherwise, if you (deliberately or accidentally or incidentally - e.g. when storing your object in a container that sometimes copies it around, such as a std::vector) copy your object, then the first copy destructored will delete the map, any other copy that tries to use it will likely crash, and any other copy's destructor that also tries to delete it will also have undefined behaviour.

Do I have to manually call to delete map.

Yes, in your code you do.

A better alternative is to use a smart pointer whose own destructor will delete the pointed-to object.

As I get crash if I call delete in the constructor in my program.

Well, if you call delete after the new, then the constructor won't crash, but you wouldn't have a map object to use after the constructor returns, and if you then try to delete it again in the destructor the you get undefined behaviour which may well manifest as a crash.

If you want to delete the map earlier than the destructor sometimes, you can set the pointer to NULL so that a future delete will do nothing safely. You should then check for NULL before trying to use the map.

Like I could add a method to Level called say destroy map where I delete map. But, was wondering why I can't add delete into the destructor.

As above, you can have destroy_map, but it must coordinate with the destructor.

When there's no compelling reason to do otherwise, it's better to make the map member data, not storing it by reference. When a pointer is useful, use a smart pointer if at all possible. If you want to implement explicit manual memory management, be wary of the issues above.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
-3

This is an unusual way to do it. Normally, an object's lifetime is determined by factors outside of the object.

But in fact MFC used to (still does?) do exactly this when a Window is being destroyed. (In response to WM_NCDESTROY, I believe.) This ensures you don't have the Window instances leaking memory after the window is gone.

So I would say it is valid in some cases. You might call it class suicide!

Jonathan Wood
  • 65,341
  • 71
  • 269
  • 466