Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there a way to remove a key from a C++ map without deleting the contents?

I have a Class named Shape, and a ShapeStorage Class. ShapeStorage class has a map...

std::map<int, Shape*> shapes;

and a function...

Shape * ReturnShapePointer(int key)  
{  
    Shape* shape = shapes[key];  
    shapes.erase(key);  
    return shape;  
}

My goal is to be able to have my main class instantiate a ShapeStorage object, store some Shape* in the shapes map. Then later on I want to delete it from my map, but not delete the value itself. I want my main class to still be able to access the value.

I have tried making it, and my pointer still returns correct values, but I'm afraid that since the destructor is being called for Shape when I delete the pointer from my map, so it's just garbage data at that point.

Is there any way around this?

like image 342
joshua Avatar asked Feb 22 '23 06:02

joshua


2 Answers

If you're storing pointers, map will not call your destructor. If it's getting called, it's getting called somewhere else.

Try running this example:

#include <iostream>
#include <map>

class Shape {
public:
    ~Shape() {
        std::cout << "Shape deleted" << std::endl;
    }
};

int main(int argc, char *argv[]) {
    std::map<int, Shape *> shapes;
    shapes[1] = new Shape();
    std::cout << "Shape added" << std::endl;
    shapes.erase(1);
    std::cout << "Shape removed from map, now exiting" << std::endl;
}

You should get this:

Shape added
Shape removed from map, now exiting
like image 68
LnxPrgr3 Avatar answered Mar 22 '23 22:03

LnxPrgr3


Your map only holds pointers to Shapes. Removing a pointer from a map has no effect whatsoever on the object it points to, it only destroys the pointer in the map.

Also, your function will perform a lookup by key twice. Once when using operator [] and second time when calling erase () with a key. Here is a better way of doing this:

Shape *ReturnShapePointer (int key)  
{  
    Shape *shape;
    std::map<int, Shape*>::iterator it = shapes.find (key);

    if (it != shapes.end ())
    {
        shape = it->second;
        shapes.erase (it);
    }
    else
    {
        shape = NULL;
    }

    return shape;  
}
like image 37
David Schwartz Avatar answered Mar 22 '23 22:03

David Schwartz