c++中std::map中的Const char *重复数据

const char * duplicate data inside of std::map in c++

本文关键字:数据 char 中的 std map c++ Const      更新时间:2023-10-16

我有一个罕见的问题。

我把一个struct存储到std::map中,插入第一个数据并正常运行,但是当我试图存储多个结构体数据时,所有"秒"值的所有const char*,在结构体内部丢失,并被新数据取代。

我恢复代码:

struct Emitter{
.
.
const char * name;
const char * file;
} 
Emitter metadata;

在我插入结构体之前,我用这段代码填充const char *变量(我从XML中获得信息)

std::string name_tmp= atts.getString("name", "ed");
char tmp[50];
strcpy(tmp, name_tmp.c_str());
metadata.name= tmp;
std::string file_tmp= atts.getString("file", "ed");
char tmp2[50];
strcpy(tmp2, file_tmp.c_str());
metadata.file= tmp2;

映射的键,是Emitter结构体中的名称;

typedef std::map<std::string, Emitter> Dictionary;
typedef std::pair<std::string, Emitter> Defination;
Dictionary::iterator it = map.find(name);
        if (it != map.end())
            map[metadata.name] = data;
        else{
            if (map.size() == 0) 
                map.insert(Defination(metadata.name, metadata));
            else{
                ParticlesDictionary::iterator i = map.begin();
                map.insert(i, Defination(metadata.name, metadata));
            }
        }

当我打印insert堆栈输出的过程时,我得到这个:

// key ---> struct value (name) ---> struct value (file)
//first time
  key1 --> eddy --> fileName1
//second time
  key1 --> eddy1-->fileName2
  key2 --> eddy1-->fileName2
//third time
  key1 --> eddy2-->fileName3
  key2 --> eddy2-->fileName3
  key3 --> eddy2-->fileName3

为什么会发生这种情况?

请帮

您的const char*字段指向不属于struct的缓冲区。这意味着当数组tmptmp2超出作用域时,它们使用的空间可用于其他数据。

在您的情况下,它被重用为下一个struct。要解决这个问题,应该分配由struct拥有的内存:要么用std::string字段替换const char*字段,要么使用newdelete

无论你是在问一个关于SO的问题,还是你想自己解决这样的问题,第一步都是建立一个MVCE或SSCE——一个小的、离散的问题再现。

在你的代码中,这将使我们关注以下内容:

#include <iostream>
struct A {
    const char* text;
};
void f(A& a, const char* text) {
    char localTxt[50];
    strcpy(lt, text);
    a.text = localTxt;
}
int main() {
    A a, b;
    f(a, "hello");
    f(b, "world");
    std::cout << "But afterwards:" << std::endl;
    std::cout << "a = " << a.text << ", b = " << b.text << "n";   
}

我们已经抛弃了你在这里所做的大部分事情,并专注于"当我将这个值放入结构中时会发生什么"。

这里的问题是localText存在于堆栈上,我们取了它的地址并把放入结构体中。指针是一个包含地址的数值。当我们这样做的时候,没有什么神奇的事情发生:

char a[] = "hello";
char* b = a;

b现在指向 a,仍然只有一个字符串的副本。

同时,整个代码块似乎都可能导致这种问题。

class Emitter {
    std::string name, file;
};
void myFunc() {
     metadata.name = atts.getString("name", "ed");
     metadata.file = atts.getString("file", "ed");
}

如果这对你不起作用,你可以考虑:

const std::string& name = atts.getString("name", "ed");
metadata.name = new char[] (name.length() + 1); // +1 for 
std::copy(metadata.name, name.c_str());

但要注意你现在负责delete[]内存:

class Emitter {
    const char* name;
    const char* file;
    Emitter() : name(nullptr), file(nullptr) {}
    ~Emitter() {
        if (name)
            delete [] name;
        if (file)
            delete [] file;
    }
    // ...
};