在 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*
,然后将这些文本存储在 id
、value
变量中,然后将 id
、value
作为新项插入。
前面的步骤发生在从数据库中获取的每个数据上。
进一步理清思路:
例如,从数据库中提取了三行 (fruits
、vegetables
、sweets
)。
自然地,当将这三个数据插入到地图容器中时,容器中的项目数将是三个项目 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
的析构函数将处理清理,无论范围是如何离开的。
首先,我有以下代码:
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*
,然后将这些文本存储在 id
、value
变量中,然后将 id
、value
作为新项插入。
前面的步骤发生在从数据库中获取的每个数据上。
进一步理清思路:
例如,从数据库中提取了三行 (fruits
、vegetables
、sweets
)。
自然地,当将这三个数据插入到地图容器中时,容器中的项目数将是三个项目 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
的析构函数将处理清理,无论范围是如何离开的。