noob
noob

Reputation: 11

How to create a map of unique object keys and objects in c++?

I tried the following:

class Obj{
public:
    int id;
    static int count;
    static map<int, Obj> ObjMap;

    Obj(){
        id = count++;
        ObjMap[id] = *this;
    }
};
int Obj::count = 0;
map<int, Obj> Obj::ObjMap;

but when i try to create an object inside main() the program terminates automaticaclly.

Upvotes: 1

Views: 261

Answers (2)

utnapistim
utnapistim

Reputation: 27365

Your map is holding object by value. This means it is storing copies of the objects:

When you add an object to the map in the constructor of Obj, this adds a new instance of Obj to the map; Within the constructor of this new instance, it is also added to the map, which creates a new instance --- and the loop goes on and on forever.

The solution requires:

  • storing addresses to objects in the map:

    static map<int, Obj*> ObjMap;
    

    constructor implementation:

    Obj() {
      id = count++;
      ObjMap[id] = this;
    }
    
  • adding an implementation of the copy constructor and assignment operator:

    these would have their own id (copy constructor also increments the count) and copying an existing object would not copy the id - only any other values the object has. The copy constructor would have to register itself in the map as well.

  • adding move constructor and copy from temporary: these would (I assume) reuse an id, and replace the original in the map?.

  • adding a destructor, which would remove objects from the map. Otherwise, when an object goes out of scope, you will be left with invalid addresses in your map.

Upvotes: 1

463035818_is_not_an_ai
463035818_is_not_an_ai

Reputation: 122233

std::map::operator[] is a little exotic and holds some surprises. It is neither just element access nor just to insert elements (that would be at() or insert resp.). What operator[] actually does is: If no element with provided key is found it creates one with default constructed mapped value and then it returns a reference to that element.

As mentioned in a comment, you have an infinite loop, because before calling [id] there was no element with that key, hence the default constructor is called again and again and again.

To insert an element in a map use insert:

ObjMap.insert({id,*this});

Also you do not need to keep track of count manually. Bookkeeping of a containers size seperate from the container is error prone. Your count is always equal to ObjMap.size(), hence you can use that.

Upvotes: 3

Related Questions