Saucy Dumpling
Saucy Dumpling

Reputation: 148

C++ map in class is not saving new keys

Basically I have a class that contains a map of structs that I have also defined. In the class, I have a member function to create a new struct and add it to the map (which takes a const char* as the key). For some reason, my map only seems to be storing the most recent key added, but it does store the value correctly.

Here is a snippet of my relevant code:

#include <map>
struct PlotData{
    int item_count;
    PlotData(){
        item_count = 0;
    }
};

Class PlotConfig{
public:
    std::map <const char*, PlotData> plots;

    void add_set(const char* key){
        plots[key] = PlotData();

        // added prints to see what's going on
        printf("Printing all plot names... Key is %s\n", key);
        for (std::map<const char*, PlotData>::iterator it=plots.begin(); it!=plots.end(); ++it){
            printf("Key: %s, Items at key: %d\n", it->first, it->second.item_count);
        }
        printf("Done\n)

    }
    void delete_set(const char* key){
        plots.erase(key);
    }
}

It may be of relevance that I'm actually wrapping this in cython and calling it from python using a custom imgui library that is also wrapped in cython, but basically, from my python, I can call like this:

conf = PlotConfig()
conf.add_set("First")
conf.add_set("Second")
conf.add_set("Third")

and I get the output

Printing all plot names... Key is First
Key: First, Items at key: 0
Done

Printing all plot names.. Key is Second
Key: , Items at key: 0
Key: Second, Items at key: 0
Done

Printing all plot names.. Key is Third
Key: , Items at key: 0
Key: , Items at key: 0
Key: Third, Items at key: 0
Done

If people are curious, there is an intermediary cython class that actually wraps PlotConfig and its functions, and when I pass a key from Python, in the cython, I use key.encode('UTF-8') to encode it into a byte string for use in C++. Aanyways, it appears that my keys are only storing temporarily. When I call delete_set() with a key, it does not properly delete because it isn't seeing the keys.

Any ideas what's going on?

Upvotes: 0

Views: 341

Answers (1)

NutCracker
NutCracker

Reputation: 12263

If you want to use char * you need to give a comparison functor to the map. Otherwise, it's comparing the pointer, not the null-terminated string it points to.

Something like this:

struct cmp {
   bool operator()(char const *a, char const *b) const {
      return std::strcmp(a, b) < 0;
   }
};

std::map<const char *, PlotData, cmp> myMap;

One additional issue (as pointed out in one of the comments) when using char * as a key is that storing pointers only does a shallow copy, and the output shows that the data pointed to goes out of scope.

If you want your keys to be null-terminated string, I suggest using std::string instead.

Upvotes: 6

Related Questions