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

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

本文关键字:覆盖 第一个 元素 映射 stl 插入 新项目      更新时间:2023-10-16

首先,我有以下代码:

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() 复制返回此方法sql->getValue(0)的文本,然后将该文本从 const unsigned char* 转换为 const char*,然后将这些文本存储在id 中,value变量,然后插入idvalue作为新项。前面的步骤发生在从数据库获取的每个数据上。

进一步澄清这个想法:
例如,从数据库中获取了三行(fruitsvegetablessweets)。
当然,当将这三个数据插入地图容器时,容器中的项目数将是三个项目第一fruits),第二vegetables),第三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 的析构函数将处理清理,而不管范围如何离开。