Eduardo
Eduardo

Reputation: 7141

Delete allocated memory in a STL map in C++

i am using a map to store an pair (int and class) using the following:

#include <iostream>
#include <utility>
#include <map>
using namespace std;

class abstractclass{...};

class derivedclass : public abstractclass{...};

typedef map<int,abstractclass*> dBase;

int main(){
    dBase db;
    db.insert(pair<int,abstractclass*>(123,new derivedclass));
    db.insert(pair<int,abstractclass*>(124,new derivedclass));
}

How do i then delete the memory allocated to this? I need to be able to use insert a user defined amount of times so a method that can delete every database entry is preferred, thanks!

If theres a way i can do this without using memory allocation that would also be useful

Upvotes: 3

Views: 3152

Answers (3)

Mark B
Mark B

Reputation: 96233

As long as your abstractclass has a virtual destructor, you can simply iterate over all the items in the container and delete the second component of the item to free the memory. There are multiple ways of doing this: For example for loop, or for_each with a functor or lambda.

EDIT: Upon further review, it appears that the map has ownership here, and your life will be much easier if you either use a map of shared_ptr (from boost or C++11), or use a boost::ptr_map instead. Then you don't have to worry about cleaning up the map at all - you can just use db.clear(); and all the items will be cleaned up automatically. Either of these containers would also help with managing memory in the face of inserting duplicate items.

Upvotes: 4

DarkWanderer
DarkWanderer

Reputation: 8866

You can use a smart pointer in your container:

#include <iostream>
#include <utility>
#include <map>
#include <memory>
using namespace std;

class abstractclass{...};

class derivedclass : public abstractclass{...};

typedef map<int,shared_ptr<abstractclass>> dBase;

int main(){
    dBase db;
    shared_ptr<abstractclass> ptr1(new derivedclass);
    shared_ptr<abstractclass> ptr2(new derivedclass);
    db.insert(pair<int,shared_ptr<abstractclass>>(123,ptr1));
    db.insert(pair<int,shared_ptr<abstractclass>>(124,ptr2));
}

The shared pointers will give a little bit of overhead here, but the advantages are:

  1. You don't have to care about deleting your objects - they will get deleted as soon as the map is destroyed.
  2. You can safely create a new object and try to insert it into the map - if the insertion fails (even with exception), the allocated object will be safely destroyed.
  3. You can insert an empty pointer and reset() it later with an actually created value (i.e. to not actually create an object, if a value with such key already exists)

Upvotes: 3

syam
syam

Reputation: 15069

Due to your class hierarchy you obviously can't just store your abstractclass objects by value in the map or you'd run into the infamous object slicing problem.

The usual way to solve this problem is to use smart pointers, eg. std::unique_ptr or std::shared_ptr (both C++11, for C++03 never use std::auto_ptr in containers since it is broken, but you can safely use the boost smart pointers instead).

So your map type would become eg. std::map<int, std::unique_ptr<abstractclass>>. Then you don't need to bother any more about deleting the objects, when they are removed from the map the smart pointer will automatically take care of it.

Another solution is to delete all the items yourself (like @MarkB said) but this is very error prone so smart pointers are usually preferred when possible.

Upvotes: 11

Related Questions