在 stl 映射中插入新项目时,会覆盖第一个元素

When insert a new item in stl map, occurs an overwrite to first element

首先,我有以下代码:

map<char*, char*> records;

// id, value are buffer variables to store the text that returns from `strcpy()` 
char *id = (char*)malloc(sizeof(char*) * 20);
char *value = (char*)malloc(sizeof(char*) * 20);

sql->open(dbFile);
sql->query("SELECT * FROM categories");
while(sql->fetch() != SQLITE_DONE){

    // copy the text that returns from `sql->getValue`, then convert that text from `const unsigned char*` to `const char*` 
    strcpy(id, reinterpret_cast<const char*>(sql->getValue(0)));
    strcpy(value, reinterpret_cast<const char*>(sql->getValue(1)));

    // insert the values that in `id`,`value` as new item
    records.insert(pair<char*, char*>(id, value));           
}
free(id);
free(value);

前面代码的想法是使用 strcopy() 复制 returns 此方法 sql->getValue(0) 的文本,然后将该文本从 const unsigned char* 转换为 const char*,然后将这些文本存储在 idvalue 变量中,然后将 idvalue 作为新项插入。 前面的步骤发生在从数据库中获取的每个数据上。

进一步理清思路:
例如,从数据库中提取了三行 (fruitsvegetablessweets)。
自然地,当将这三个数据插入到地图容器中时,容器中的项目数将是三个项目 first(fruits), second(vegetables), third(sweets).

在我的例子中,当检查项目数量时,我发现只有一个项目,项目是sweets

现在,我很惊讶,剩下的物品在哪里?

您正在三次覆盖相同的内存块,并三次存储指向这些块的指针。就地图而言,每次都是相同的值,因为指针永远不会改变。

看来您真正想要的是字符串映射,而不是指针。如果您使用 std::string:

会容易得多
#include <string>

...

map<string, string> records;

string id, value; // size of allocation will be handled by the string class.

sql->open(dbFile);
sql->query("SELECT * FROM categories");
while(sql->fetch() != SQLITE_DONE){
  // string has an assignment operator from C-style strings
  id    = reinterpret_cast<const char*>(sql->getValue(0));
  value = reinterpret_cast<const char*>(sql->getValue(1));

  // more readable way of writing the insert. id, value will be copied into
  // the map.
  records[id] = value;
}

// freeing unnecessary; string class handles it when id, value go out of scope.

这还有一个优点,即无需 try-catch-block 即可使代码异常安全(至少是字符串)。 std::string 的析构函数将处理清理,无论范围是如何离开的。