Карта C ++ в классе не сохраняет новые ключи - PullRequest
0 голосов
/ 22 января 2020

В основном у меня есть класс, который содержит карту структур, которые я также определил. В классе у меня есть функция-член для создания новой структуры и добавления ее на карту (в качестве ключа используется const char*). По какой-то причине моя карта, похоже, хранит только самый последний добавленный ключ, но она правильно хранит значение.

Вот фрагмент моего соответствующего кода:

#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);
    }
}

Это может быть уместно, что я фактически обертываю это в cython и вызываю его из python, используя собственную библиотеку im gui, которая также обернута в cython, но в основном из моего python я могу вызвать так:

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

и я получаю вывод

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

Если людям интересно, существует промежуточный класс Cython, который фактически оборачивает PlotConfig и его функции, и когда я передаю ключ от Python, в цитоне я использую key.encode('UTF-8') для кодирования его в байтовую строку для использования в C ++. В любом случае, кажется, что мои ключи хранятся только временно. Когда я звоню delete_set() с ключом, он не удаляется должным образом, потому что не видит ключей.

Есть идеи, что происходит?

1 Ответ

6 голосов
/ 22 января 2020

Если вы хотите использовать char *, вам нужно добавить на карту функтор сравнения. В противном случае он сравнивает указатель, а не строку с нулевым символом в конце, на которую он указывает.

Примерно так:

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

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

Одна дополнительная проблема (как указано в одном из комментариев), когда использование char * в качестве ключа означает, что хранение указателей делает только поверхностное копирование, а вывод показывает, что данные, на которые указывают, выходят за рамки.

Если вы хотите, чтобы ваши ключи были строкой с нулевым символом в конце, я предложите использовать std::string вместо.

...