C++STL映射:insert正在存储空指针

C++ STL map: insert is storing null pointers

本文关键字:存储 空指针 insert 映射 C++STL      更新时间:2023-10-16

我有一个简单的类

    class symbol_entry
{
private:
    static unsigned long uid;
public:
    std::string name;
    std::string filename;
    unsigned int line_number;
    unsigned int column_number;
    symbol_entry* parent_symbol;
    std::map<const char*,symbol_entry*> child_symbols;
    unsigned long type_flags;
public:
    symbol_entry();
    symbol_entry(const char* name,
                 const char* filename,
                 int line_number,
                 int column_number,
                 symbol_entry* parent_symbol,
                 unsigned long type_flags);
    ~symbol_entry();
    symbol_entry* get_child(const char* name);
    bool put_child(symbol_entry* child);
};

以下是symbol_entry::put_child的实现;

bool symbol_entry::put_child(symbol_entry* child)
{   
    if(child_symbols[child->name.c_str()])
        return false;
    child_symbols.insert(std::make_pair(child->name.c_str(),child));
    return true;
}

每当我进行这样的测试时;

symbol_entry* tsym=new symbol_entry("test","$",0,0,0,0);
symbol_entry* tcsym=new symbol_entry("test_child","$",0,0,0,0);
tsym->put_child(tcsym);
std::cout<<tsym->child_symbols.begin()->first<<" => "<<tsym->child_symbols.begin()->second<<std::endl;

child_symbols.begin()->第二个是存储一个空指针。我无法解决这个问题,并尝试了许多变体,包括const和对的引用。

child_symbols[child->name.c_str()]将始终创建并返回一个新的映射条目(一个NULL条目),然后child_symbols.insert(...)不执行任何操作(因此映射中的值保持为NULL)。检查钥匙是否已经在地图中的正确方法是使用find:

if (child_symbols.find(...) != child_symbols.end()) // already exists

您正在按值比较指针。您需要比较它们指向的内容。示例:

std::string s1 = "Hello World!";
std::string s2 = s1;
s1.c_str() != s2.c_str()

这就是为什么在C++程序中使用C字符串绝对不合适的原因——std::string按值进行比较。

child_symbols[child->name.c_str()]不会做您认为它会做的事情:它每次都会插入一个默认对象,在您的情况下是一个symbol_entry指针。我可能错了,但我认为

if(child_symbols[child->name.c_str()])

将始终计算为true,因为std::map将为您插入一个条目。

这:

child_symbols.insert(std::make_pair(child->name.c_str(),child));

不正常:您正在存储c_str()的结果,该结果不是持久值。它为您提供了一个指向C字符串的指针,该字符串在您调用后立即有效,但对于以后的存储和读取无效。您应该使用std::string作为映射的键类型。

如果映射中已经存在元素,则插入将不起任何作用。您的检查child_symbols[child->name.c_str()]将创建处于默认状态的元素,因此会发生这种情况。

您可以使用find来进行检查,但insert已经内置了以下内容:

bool symbol_entry::put_child(symbol_entry* child)
{
    return child_symbols.insert(std::make_pair(child->name,child)).second;
}

编辑:此外,DeadMG所说的-使用std::string而不是const char*来修复