我有一个简单的课程
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() - &gt;第二个是存储空指针。我无法解决这个问题,并尝试了许多变体,包括const和引用,但有用。
答案 0 :(得分:5)
child_symbols[child->name.c_str()]
将始终创建并返回一个新的映射条目(NULL值),然后child_symbols.insert(...)
不执行任何操作(因此映射中的值保持为NULL)。检查密钥是否已在地图中的正确方法是使用find
:
if (child_symbols.find(...) != child_symbols.end()) // already exists
答案 1 :(得分:4)
您按价值比较指针。您需要比较他们指向的内容。例如:
std::string s1 = "Hello World!";
std::string s2 = s1;
s1.c_str() != s2.c_str()
这就是为什么在C ++程序中使用C字符串绝对不合适的原因 - std::string
按值进行比较。
答案 2 :(得分:1)
child_symbols[child->name.c_str()]
没有按照您的想法执行操作:每次都插入一个默认对象,在您的情况下是symbol_entry
指针。我错了,但我认为
if(child_symbols[child->name.c_str()])
将始终评估为true
,因为std::map
会为您插入一个条目。
答案 3 :(得分:1)
此:
child_symbols.insert(std::make_pair(child->name.c_str(),child));
不行:您存储的c_str()结果不是持久值。它为您提供了一个指向C字符串的指针,该字符串在您调用之后立即生效,但它对于以后存储和读取无效。您应该使用std :: string作为其键类型。
答案 4 :(得分:0)
如果地图中已存在元素,则插入将不执行任何操作。您的检查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*
来修复